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 android.app.AlarmManager; 20 import android.app.PendingIntent; 21 import android.content.BroadcastReceiver; 22 import android.content.ContentResolver; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.IntentFilter; 26 import android.content.SharedPreferences; 27 import android.database.ContentObserver; 28 import android.net.ConnectivityManager; 29 import android.net.LinkProperties; 30 import android.net.NetworkCapabilities; 31 import android.net.NetworkInfo; 32 import android.net.TrafficStats; 33 import android.net.wifi.WifiManager; 34 import android.os.AsyncResult; 35 import android.os.Build; 36 import android.os.Bundle; 37 import android.os.Handler; 38 import android.os.HandlerThread; 39 import android.os.Message; 40 import android.os.SystemClock; 41 import android.os.SystemProperties; 42 import android.preference.PreferenceManager; 43 import android.provider.Settings; 44 import android.provider.Settings.SettingNotFoundException; 45 import android.telephony.SubscriptionManager; 46 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; 47 import android.telephony.TelephonyManager; 48 import android.text.TextUtils; 49 import android.util.EventLog; 50 import android.telephony.Rlog; 51 52 import com.android.internal.R; 53 import com.android.internal.telephony.DctConstants; 54 import com.android.internal.telephony.EventLogTags; 55 import com.android.internal.telephony.Phone; 56 import com.android.internal.telephony.PhoneBase; 57 import com.android.internal.telephony.PhoneConstants; 58 import com.android.internal.telephony.uicc.IccRecords; 59 import com.android.internal.telephony.uicc.UiccController; 60 import com.android.internal.util.AsyncChannel; 61 import com.android.internal.util.ArrayUtils; 62 63 import java.io.FileDescriptor; 64 import java.io.PrintWriter; 65 import java.util.ArrayList; 66 import java.util.Comparator; 67 import java.util.HashMap; 68 import java.util.List; 69 import java.util.Map.Entry; 70 import java.util.Set; 71 import java.util.concurrent.ConcurrentHashMap; 72 import java.util.concurrent.atomic.AtomicInteger; 73 import java.util.concurrent.atomic.AtomicReference; 74 import java.util.PriorityQueue; 75 76 /** 77 * {@hide} 78 */ 79 public abstract class DcTrackerBase extends Handler { 80 protected static final boolean DBG = true; 81 protected static final boolean VDBG = false; // STOPSHIP if true 82 protected static final boolean VDBG_STALL = true; // STOPSHIP if true 83 protected static final boolean RADIO_TESTS = false; 84 85 static boolean mIsCleanupRequired = false; 86 /** 87 * Constants for the data connection activity: 88 * physical link down/up 89 */ 90 protected static final int DATA_CONNECTION_ACTIVE_PH_LINK_INACTIVE = 0; 91 protected static final int DATA_CONNECTION_ACTIVE_PH_LINK_DOWN = 1; 92 protected static final int DATA_CONNECTION_ACTIVE_PH_LINK_UP = 2; 93 94 /** Delay between APN attempts. 95 Note the property override mechanism is there just for testing purpose only. */ 96 protected static final int APN_DELAY_DEFAULT_MILLIS = 20000; 97 98 /** Delay between APN attempts when in fail fast mode */ 99 protected static final int APN_FAIL_FAST_DELAY_DEFAULT_MILLIS = 3000; 100 101 AlarmManager mAlarmManager; 102 103 protected Object mDataEnabledLock = new Object(); 104 105 // responds to the setInternalDataEnabled call - used internally to turn off data 106 // for example during emergency calls 107 protected boolean mInternalDataEnabled = true; 108 109 // responds to public (user) API to enable/disable data use 110 // independent of mInternalDataEnabled and requests for APN access 111 // persisted 112 protected boolean mUserDataEnabled = true; 113 114 // TODO: move away from static state once 5587429 is fixed. 115 protected static boolean sPolicyDataEnabled = true; 116 117 private boolean[] mDataEnabled = new boolean[DctConstants.APN_NUM_TYPES]; 118 119 private int mEnabledCount = 0; 120 121 /* Currently requested APN type (TODO: This should probably be a parameter not a member) */ 122 protected String mRequestedApnType = PhoneConstants.APN_TYPE_DEFAULT; 123 124 /** Retry configuration: A doubling of retry times from 5secs to 30minutes */ 125 protected static final String DEFAULT_DATA_RETRY_CONFIG = "default_randomization=2000," 126 + "5000,10000,20000,40000,80000:5000,160000:5000," 127 + "320000:5000,640000:5000,1280000:5000,1800000:5000"; 128 129 /** Retry configuration for secondary networks: 4 tries in 20 sec */ 130 protected static final String SECONDARY_DATA_RETRY_CONFIG = 131 "max_retries=3, 5000, 5000, 5000"; 132 133 /** Slow poll when attempting connection recovery. */ 134 protected static final int POLL_NETSTAT_SLOW_MILLIS = 5000; 135 /** Default max failure count before attempting to network re-registration. */ 136 protected static final int DEFAULT_MAX_PDP_RESET_FAIL = 3; 137 138 /** 139 * After detecting a potential connection problem, this is the max number 140 * of subsequent polls before attempting recovery. 141 */ 142 protected static final int NO_RECV_POLL_LIMIT = 24; 143 // 1 sec. default polling interval when screen is on. 144 protected static final int POLL_NETSTAT_MILLIS = 1000; 145 // 10 min. default polling interval when screen is off. 146 protected static final int POLL_NETSTAT_SCREEN_OFF_MILLIS = 1000*60*10; 147 // 2 min for round trip time 148 protected static final int POLL_LONGEST_RTT = 120 * 1000; 149 // Default sent packets without ack which triggers initial recovery steps 150 protected static final int NUMBER_SENT_PACKETS_OF_HANG = 10; 151 // how long to wait before switching back to default APN 152 protected static final int RESTORE_DEFAULT_APN_DELAY = 1 * 60 * 1000; 153 // system property that can override the above value 154 protected static final String APN_RESTORE_DELAY_PROP_NAME = "android.telephony.apn-restore"; 155 // represents an invalid IP address 156 protected static final String NULL_IP = "0.0.0.0"; 157 158 // Default for the data stall alarm while non-aggressive stall detection 159 protected static final int DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS_DEFAULT = 1000 * 60 * 6; 160 // Default for the data stall alarm for aggressive stall detection 161 protected static final int DATA_STALL_ALARM_AGGRESSIVE_DELAY_IN_MS_DEFAULT = 1000 * 60; 162 // If attempt is less than this value we're doing first level recovery 163 protected static final int DATA_STALL_NO_RECV_POLL_LIMIT = 1; 164 // Tag for tracking stale alarms 165 protected static final String DATA_STALL_ALARM_TAG_EXTRA = "data.stall.alram.tag"; 166 167 protected static final boolean DATA_STALL_SUSPECTED = true; 168 protected static final boolean DATA_STALL_NOT_SUSPECTED = false; 169 170 protected String RADIO_RESET_PROPERTY = "gsm.radioreset"; 171 172 protected static final String INTENT_RECONNECT_ALARM = 173 "com.android.internal.telephony.data-reconnect"; 174 protected static final String INTENT_RECONNECT_ALARM_EXTRA_TYPE = "reconnect_alarm_extra_type"; 175 protected static final String INTENT_RECONNECT_ALARM_EXTRA_REASON = 176 "reconnect_alarm_extra_reason"; 177 178 protected static final String INTENT_RESTART_TRYSETUP_ALARM = 179 "com.android.internal.telephony.data-restart-trysetup"; 180 protected static final String INTENT_RESTART_TRYSETUP_ALARM_EXTRA_TYPE = 181 "restart_trysetup_alarm_extra_type"; 182 183 protected static final String INTENT_DATA_STALL_ALARM = 184 "com.android.internal.telephony.data-stall"; 185 186 187 188 protected static final String DEFALUT_DATA_ON_BOOT_PROP = "net.def_data_on_boot"; 189 190 protected DcTesterFailBringUpAll mDcTesterFailBringUpAll; 191 protected DcController mDcc; 192 193 // member variables 194 protected PhoneBase mPhone; 195 protected UiccController mUiccController; 196 protected AtomicReference<IccRecords> mIccRecords = new AtomicReference<IccRecords>(); 197 protected DctConstants.Activity mActivity = DctConstants.Activity.NONE; 198 protected DctConstants.State mState = DctConstants.State.IDLE; 199 protected Handler mDataConnectionTracker = null; 200 201 protected long mTxPkts; 202 protected long mRxPkts; 203 protected int mNetStatPollPeriod; 204 protected boolean mNetStatPollEnabled = false; 205 206 protected TxRxSum mDataStallTxRxSum = new TxRxSum(0, 0); 207 // Used to track stale data stall alarms. 208 protected int mDataStallAlarmTag = (int) SystemClock.elapsedRealtime(); 209 // The current data stall alarm intent 210 protected PendingIntent mDataStallAlarmIntent = null; 211 // Number of packets sent since the last received packet 212 protected long mSentSinceLastRecv; 213 // Controls when a simple recovery attempt it to be tried 214 protected int mNoRecvPollCount = 0; 215 // Refrence counter for enabling fail fast 216 protected static int sEnableFailFastRefCounter = 0; 217 // True if data stall detection is enabled 218 protected volatile boolean mDataStallDetectionEnabled = true; 219 220 protected volatile boolean mFailFast = false; 221 222 // True when in voice call 223 protected boolean mInVoiceCall = false; 224 225 // wifi connection status will be updated by sticky intent 226 protected boolean mIsWifiConnected = false; 227 228 /** Intent sent when the reconnect alarm fires. */ 229 protected PendingIntent mReconnectIntent = null; 230 231 /** CID of active data connection */ 232 protected int mCidActive; 233 234 // When false we will not auto attach and manually attaching is required. 235 protected boolean mAutoAttachOnCreationConfig = false; 236 protected boolean mAutoAttachOnCreation = false; 237 238 // State of screen 239 // (TODO: Reconsider tying directly to screen, maybe this is 240 // really a lower power mode") 241 protected boolean mIsScreenOn = true; 242 243 /** Allows the generation of unique Id's for DataConnection objects */ 244 protected AtomicInteger mUniqueIdGenerator = new AtomicInteger(0); 245 246 /** The data connections. */ 247 protected HashMap<Integer, DataConnection> mDataConnections = 248 new HashMap<Integer, DataConnection>(); 249 250 /** The data connection async channels */ 251 protected HashMap<Integer, DcAsyncChannel> mDataConnectionAcHashMap = 252 new HashMap<Integer, DcAsyncChannel>(); 253 254 /** Convert an ApnType string to Id (TODO: Use "enumeration" instead of String for ApnType) */ 255 protected HashMap<String, Integer> mApnToDataConnectionId = 256 new HashMap<String, Integer>(); 257 258 /** Phone.APN_TYPE_* ===> ApnContext */ 259 protected final ConcurrentHashMap<String, ApnContext> mApnContexts = 260 new ConcurrentHashMap<String, ApnContext>(); 261 262 /** kept in sync with mApnContexts 263 * Higher numbers are higher priority and sorted so highest priority is first */ 264 protected final PriorityQueue<ApnContext>mPrioritySortedApnContexts = 265 new PriorityQueue<ApnContext>(5, 266 new Comparator<ApnContext>() { 267 public int compare(ApnContext c1, ApnContext c2) { 268 return c2.priority - c1.priority; 269 } 270 } ); 271 272 /* Currently active APN */ 273 protected ApnSetting mActiveApn; 274 275 /** allApns holds all apns */ 276 protected ArrayList<ApnSetting> mAllApnSettings = null; 277 278 /** preferred apn */ 279 protected ApnSetting mPreferredApn = null; 280 281 /** Is packet service restricted by network */ 282 protected boolean mIsPsRestricted = false; 283 284 /** emergency apn Setting*/ 285 protected ApnSetting mEmergencyApn = null; 286 287 /* Once disposed dont handle any messages */ 288 protected boolean mIsDisposed = false; 289 290 protected ContentResolver mResolver; 291 292 /* Set to true with CMD_ENABLE_MOBILE_PROVISIONING */ 293 protected boolean mIsProvisioning = false; 294 295 /* The Url passed as object parameter in CMD_ENABLE_MOBILE_PROVISIONING */ 296 protected String mProvisioningUrl = null; 297 298 /* Intent for the provisioning apn alarm */ 299 protected static final String INTENT_PROVISIONING_APN_ALARM = 300 "com.android.internal.telephony.provisioning_apn_alarm"; 301 302 /* Tag for tracking stale alarms */ 303 protected static final String PROVISIONING_APN_ALARM_TAG_EXTRA = "provisioning.apn.alarm.tag"; 304 305 /* Debug property for overriding the PROVISIONING_APN_ALARM_DELAY_IN_MS */ 306 protected static final String DEBUG_PROV_APN_ALARM = 307 "persist.debug.prov_apn_alarm"; 308 309 /* Default for the provisioning apn alarm timeout */ 310 protected static final int PROVISIONING_APN_ALARM_DELAY_IN_MS_DEFAULT = 1000 * 60 * 15; 311 312 /* The provision apn alarm intent used to disable the provisioning apn */ 313 protected PendingIntent mProvisioningApnAlarmIntent = null; 314 315 /* Used to track stale provisioning apn alarms */ 316 protected int mProvisioningApnAlarmTag = (int) SystemClock.elapsedRealtime(); 317 318 protected AsyncChannel mReplyAc = new AsyncChannel(); 319 320 protected BroadcastReceiver mIntentReceiver = new BroadcastReceiver () 321 { 322 @Override 323 public void onReceive(Context context, Intent intent) 324 { 325 String action = intent.getAction(); 326 if (DBG) log("onReceive: action=" + action); 327 if (action.equals(Intent.ACTION_SCREEN_ON)) { 328 mIsScreenOn = true; 329 stopNetStatPoll(); 330 startNetStatPoll(); 331 restartDataStallAlarm(); 332 } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { 333 mIsScreenOn = false; 334 stopNetStatPoll(); 335 startNetStatPoll(); 336 restartDataStallAlarm(); 337 } else if (action.startsWith(INTENT_RECONNECT_ALARM)) { 338 if (DBG) log("Reconnect alarm. Previous state was " + mState); 339 onActionIntentReconnectAlarm(intent); 340 } else if (action.startsWith(INTENT_RESTART_TRYSETUP_ALARM)) { 341 if (DBG) log("Restart trySetup alarm"); 342 onActionIntentRestartTrySetupAlarm(intent); 343 } else if (action.equals(INTENT_DATA_STALL_ALARM)) { 344 onActionIntentDataStallAlarm(intent); 345 } else if (action.equals(INTENT_PROVISIONING_APN_ALARM)) { 346 onActionIntentProvisioningApnAlarm(intent); 347 } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { 348 final android.net.NetworkInfo networkInfo = (NetworkInfo) 349 intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); 350 mIsWifiConnected = (networkInfo != null && networkInfo.isConnected()); 351 if (DBG) log("NETWORK_STATE_CHANGED_ACTION: mIsWifiConnected=" + mIsWifiConnected); 352 } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { 353 final boolean enabled = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 354 WifiManager.WIFI_STATE_UNKNOWN) == WifiManager.WIFI_STATE_ENABLED; 355 356 if (!enabled) { 357 // when WiFi got disabled, the NETWORK_STATE_CHANGED_ACTION 358 // quit and won't report disconnected until next enabling. 359 mIsWifiConnected = false; 360 } 361 if (DBG) log("WIFI_STATE_CHANGED_ACTION: enabled=" + enabled 362 + " mIsWifiConnected=" + mIsWifiConnected); 363 } 364 } 365 }; 366 367 private Runnable mPollNetStat = new Runnable() 368 { 369 @Override 370 public void run() { 371 updateDataActivity(); 372 373 if (mIsScreenOn) { 374 mNetStatPollPeriod = Settings.Global.getInt(mResolver, 375 Settings.Global.PDP_WATCHDOG_POLL_INTERVAL_MS, POLL_NETSTAT_MILLIS); 376 } else { 377 mNetStatPollPeriod = Settings.Global.getInt(mResolver, 378 Settings.Global.PDP_WATCHDOG_LONG_POLL_INTERVAL_MS, 379 POLL_NETSTAT_SCREEN_OFF_MILLIS); 380 } 381 382 if (mNetStatPollEnabled) { 383 mDataConnectionTracker.postDelayed(this, mNetStatPollPeriod); 384 } 385 } 386 }; 387 388 private SubscriptionManager mSubscriptionManager; 389 private final OnSubscriptionsChangedListener mOnSubscriptionsChangedListener = 390 new OnSubscriptionsChangedListener() { 391 /** 392 * Callback invoked when there is any change to any SubscriptionInfo. Typically 393 * this method would invoke {@link SubscriptionManager#getActiveSubscriptionInfoList} 394 */ 395 @Override 396 public void onSubscriptionsChanged() { 397 if (DBG) log("SubscriptionListener.onSubscriptionInfoChanged"); 398 // Set the network type, in case the radio does not restore it. 399 int subId = mPhone.getSubId(); 400 if (SubscriptionManager.isValidSubscriptionId(subId)) { 401 if (mDataRoamingSettingObserver != null) { 402 mDataRoamingSettingObserver.unregister(); 403 } 404 // Watch for changes to Settings.Global.DATA_ROAMING 405 mDataRoamingSettingObserver = new DataRoamingSettingObserver(mPhone, 406 mPhone.getContext()); 407 mDataRoamingSettingObserver.register(); 408 } 409 } 410 }; 411 412 private class DataRoamingSettingObserver extends ContentObserver { 413 DataRoamingSettingObserver(Handler handler, Context context)414 public DataRoamingSettingObserver(Handler handler, Context context) { 415 super(handler); 416 mResolver = context.getContentResolver(); 417 } 418 register()419 public void register() { 420 String contentUri; 421 if (TelephonyManager.getDefault().getSimCount() == 1) { 422 contentUri = Settings.Global.DATA_ROAMING; 423 } else { 424 contentUri = Settings.Global.DATA_ROAMING + mPhone.getSubId(); 425 } 426 427 mResolver.registerContentObserver(Settings.Global.getUriFor(contentUri), false, this); 428 } 429 unregister()430 public void unregister() { 431 mResolver.unregisterContentObserver(this); 432 } 433 434 @Override onChange(boolean selfChange)435 public void onChange(boolean selfChange) { 436 // already running on mPhone handler thread 437 if (mPhone.getServiceState().getDataRoaming()) { 438 sendMessage(obtainMessage(DctConstants.EVENT_ROAMING_ON)); 439 } 440 } 441 } 442 private DataRoamingSettingObserver mDataRoamingSettingObserver; 443 444 /** 445 * The Initial MaxRetry sent to a DataConnection as a parameter 446 * to DataConnectionAc.bringUp. This value can be defined at compile 447 * time using the SystemProperty Settings.Global.DCT_INITIAL_MAX_RETRY 448 * and at runtime using gservices to change Settings.Global.DCT_INITIAL_MAX_RETRY. 449 */ 450 private static final int DEFAULT_MDC_INITIAL_RETRY = 1; getInitialMaxRetry()451 protected int getInitialMaxRetry() { 452 if (mFailFast) { 453 return 0; 454 } 455 // Get default value from system property or use DEFAULT_MDC_INITIAL_RETRY 456 int value = SystemProperties.getInt( 457 Settings.Global.MDC_INITIAL_MAX_RETRY, DEFAULT_MDC_INITIAL_RETRY); 458 459 // Check if its been overridden 460 return Settings.Global.getInt(mResolver, 461 Settings.Global.MDC_INITIAL_MAX_RETRY, value); 462 } 463 464 /** 465 * Maintain the sum of transmit and receive packets. 466 * 467 * The packet counts are initialized and reset to -1 and 468 * remain -1 until they can be updated. 469 */ 470 public class TxRxSum { 471 public long txPkts; 472 public long rxPkts; 473 TxRxSum()474 public TxRxSum() { 475 reset(); 476 } 477 TxRxSum(long txPkts, long rxPkts)478 public TxRxSum(long txPkts, long rxPkts) { 479 this.txPkts = txPkts; 480 this.rxPkts = rxPkts; 481 } 482 TxRxSum(TxRxSum sum)483 public TxRxSum(TxRxSum sum) { 484 txPkts = sum.txPkts; 485 rxPkts = sum.rxPkts; 486 } 487 reset()488 public void reset() { 489 txPkts = -1; 490 rxPkts = -1; 491 } 492 493 @Override toString()494 public String toString() { 495 return "{txSum=" + txPkts + " rxSum=" + rxPkts + "}"; 496 } 497 updateTxRxSum()498 public void updateTxRxSum() { 499 this.txPkts = TrafficStats.getMobileTcpTxPackets(); 500 this.rxPkts = TrafficStats.getMobileTcpRxPackets(); 501 } 502 } 503 onActionIntentReconnectAlarm(Intent intent)504 protected void onActionIntentReconnectAlarm(Intent intent) { 505 String reason = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_REASON); 506 String apnType = intent.getStringExtra(INTENT_RECONNECT_ALARM_EXTRA_TYPE); 507 508 int phoneSubId = mPhone.getSubId(); 509 int currSubId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, 510 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 511 log("onActionIntentReconnectAlarm: currSubId = " + currSubId + " phoneSubId=" + phoneSubId); 512 513 // Stop reconnect if not current subId is not correct. 514 // FIXME STOPSHIP - phoneSubId is coming up as -1 way after boot and failing this? 515 if (!SubscriptionManager.isValidSubscriptionId(currSubId) || (currSubId != phoneSubId)) { 516 log("receive ReconnectAlarm but subId incorrect, ignore"); 517 return; 518 } 519 520 ApnContext apnContext = mApnContexts.get(apnType); 521 522 if (DBG) { 523 log("onActionIntentReconnectAlarm: mState=" + mState + " reason=" + reason + 524 " apnType=" + apnType + " apnContext=" + apnContext + 525 " mDataConnectionAsyncChannels=" + mDataConnectionAcHashMap); 526 } 527 528 if ((apnContext != null) && (apnContext.isEnabled())) { 529 apnContext.setReason(reason); 530 DctConstants.State apnContextState = apnContext.getState(); 531 if (DBG) { 532 log("onActionIntentReconnectAlarm: apnContext state=" + apnContextState); 533 } 534 if ((apnContextState == DctConstants.State.FAILED) 535 || (apnContextState == DctConstants.State.IDLE)) { 536 if (DBG) { 537 log("onActionIntentReconnectAlarm: state is FAILED|IDLE, disassociate"); 538 } 539 DcAsyncChannel dcac = apnContext.getDcAc(); 540 if (dcac != null) { 541 if (DBG) { 542 log("onActionIntentReconnectAlarm: tearDown apnContext=" + apnContext); 543 } 544 dcac.tearDown(apnContext, "", null); 545 } 546 apnContext.setDataConnectionAc(null); 547 apnContext.setState(DctConstants.State.IDLE); 548 } else { 549 if (DBG) log("onActionIntentReconnectAlarm: keep associated"); 550 } 551 // TODO: IF already associated should we send the EVENT_TRY_SETUP_DATA??? 552 sendMessage(obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, apnContext)); 553 554 apnContext.setReconnectIntent(null); 555 } 556 } 557 onActionIntentRestartTrySetupAlarm(Intent intent)558 protected void onActionIntentRestartTrySetupAlarm(Intent intent) { 559 String apnType = intent.getStringExtra(INTENT_RESTART_TRYSETUP_ALARM_EXTRA_TYPE); 560 ApnContext apnContext = mApnContexts.get(apnType); 561 if (DBG) { 562 log("onActionIntentRestartTrySetupAlarm: mState=" + mState + 563 " apnType=" + apnType + " apnContext=" + apnContext + 564 " mDataConnectionAsyncChannels=" + mDataConnectionAcHashMap); 565 } 566 sendMessage(obtainMessage(DctConstants.EVENT_TRY_SETUP_DATA, apnContext)); 567 } 568 onActionIntentDataStallAlarm(Intent intent)569 protected void onActionIntentDataStallAlarm(Intent intent) { 570 if (VDBG_STALL) log("onActionIntentDataStallAlarm: action=" + intent.getAction()); 571 Message msg = obtainMessage(DctConstants.EVENT_DATA_STALL_ALARM, 572 intent.getAction()); 573 msg.arg1 = intent.getIntExtra(DATA_STALL_ALARM_TAG_EXTRA, 0); 574 sendMessage(msg); 575 } 576 577 ConnectivityManager mCm; 578 579 /** 580 * Default constructor 581 */ DcTrackerBase(PhoneBase phone)582 protected DcTrackerBase(PhoneBase phone) { 583 super(); 584 mPhone = phone; 585 if (DBG) log("DCT.constructor"); 586 mResolver = mPhone.getContext().getContentResolver(); 587 mUiccController = UiccController.getInstance(); 588 mUiccController.registerForIccChanged(this, DctConstants.EVENT_ICC_CHANGED, null); 589 mAlarmManager = 590 (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE); 591 mCm = (ConnectivityManager) mPhone.getContext().getSystemService( 592 Context.CONNECTIVITY_SERVICE); 593 594 595 int phoneSubId = mPhone.getSubId(); 596 IntentFilter filter = new IntentFilter(); 597 filter.addAction(Intent.ACTION_SCREEN_ON); 598 filter.addAction(Intent.ACTION_SCREEN_OFF); 599 filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); 600 filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); 601 filter.addAction(INTENT_DATA_STALL_ALARM); 602 filter.addAction(INTENT_PROVISIONING_APN_ALARM); 603 604 mUserDataEnabled = getDataEnabled(); 605 606 mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone); 607 608 // This preference tells us 1) initial condition for "dataEnabled", 609 // and 2) whether the RIL will setup the baseband to auto-PS attach. 610 611 mDataEnabled[DctConstants.APN_DEFAULT_ID] = 612 SystemProperties.getBoolean(DEFALUT_DATA_ON_BOOT_PROP,true); 613 if (mDataEnabled[DctConstants.APN_DEFAULT_ID]) { 614 mEnabledCount++; 615 } 616 617 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mPhone.getContext()); 618 mAutoAttachOnCreation = sp.getBoolean(PhoneBase.DATA_DISABLED_ON_BOOT_KEY, false); 619 620 mSubscriptionManager = SubscriptionManager.from(mPhone.getContext()); 621 mSubscriptionManager 622 .addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener); 623 624 HandlerThread dcHandlerThread = new HandlerThread("DcHandlerThread"); 625 dcHandlerThread.start(); 626 Handler dcHandler = new Handler(dcHandlerThread.getLooper()); 627 mDcc = DcController.makeDcc(mPhone, this, dcHandler); 628 mDcTesterFailBringUpAll = new DcTesterFailBringUpAll(mPhone, dcHandler); 629 } 630 dispose()631 public void dispose() { 632 if (DBG) log("DCT.dispose"); 633 for (DcAsyncChannel dcac : mDataConnectionAcHashMap.values()) { 634 dcac.disconnect(); 635 } 636 mDataConnectionAcHashMap.clear(); 637 mIsDisposed = true; 638 mPhone.getContext().unregisterReceiver(mIntentReceiver); 639 mUiccController.unregisterForIccChanged(this); 640 if (mDataRoamingSettingObserver != null) { 641 mDataRoamingSettingObserver.unregister(); 642 } 643 mSubscriptionManager 644 .removeOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener); 645 mDcc.dispose(); 646 mDcTesterFailBringUpAll.dispose(); 647 } 648 getSubId()649 public long getSubId() { 650 return mPhone.getSubId(); 651 } 652 getActivity()653 public DctConstants.Activity getActivity() { 654 return mActivity; 655 } 656 setActivity(DctConstants.Activity activity)657 void setActivity(DctConstants.Activity activity) { 658 log("setActivity = " + activity); 659 mActivity = activity; 660 mPhone.notifyDataActivity(); 661 } 662 incApnRefCount(String name)663 public void incApnRefCount(String name) { 664 665 } 666 decApnRefCount(String name)667 public void decApnRefCount(String name) { 668 669 } 670 isApnSupported(String name)671 public boolean isApnSupported(String name) { 672 return false; 673 } 674 getApnPriority(String name)675 public int getApnPriority(String name) { 676 return -1; 677 } 678 679 isApnTypeActive(String type)680 public boolean isApnTypeActive(String type) { 681 // TODO: support simultaneous with List instead 682 if (PhoneConstants.APN_TYPE_DUN.equals(type)) { 683 ApnSetting dunApn = fetchDunApn(); 684 if (dunApn != null) { 685 return ((mActiveApn != null) && (dunApn.toString().equals(mActiveApn.toString()))); 686 } 687 } 688 return mActiveApn != null && mActiveApn.canHandleType(type); 689 } 690 fetchDunApn()691 protected ApnSetting fetchDunApn() { 692 if (SystemProperties.getBoolean("net.tethering.noprovisioning", false)) { 693 log("fetchDunApn: net.tethering.noprovisioning=true ret: null"); 694 return null; 695 } 696 int bearer = -1; 697 ApnSetting retDunSetting = null; 698 String apnData = Settings.Global.getString(mResolver, Settings.Global.TETHER_DUN_APN); 699 List<ApnSetting> dunSettings = ApnSetting.arrayFromString(apnData); 700 IccRecords r = mIccRecords.get(); 701 for (ApnSetting dunSetting : dunSettings) { 702 String operator = (r != null) ? r.getOperatorNumeric() : ""; 703 if (dunSetting.bearer != 0) { 704 if (bearer == -1) bearer = mPhone.getServiceState().getRilDataRadioTechnology(); 705 if (dunSetting.bearer != bearer) continue; 706 } 707 if (dunSetting.numeric.equals(operator)) { 708 if (dunSetting.hasMvnoParams()) { 709 if (r != null && 710 mvnoMatches(r, dunSetting.mvnoType, dunSetting.mvnoMatchData)) { 711 if (VDBG) { 712 log("fetchDunApn: global TETHER_DUN_APN dunSetting=" + dunSetting); 713 } 714 return dunSetting; 715 } 716 } else { 717 if (VDBG) log("fetchDunApn: global TETHER_DUN_APN dunSetting=" + dunSetting); 718 return dunSetting; 719 } 720 } 721 } 722 723 Context c = mPhone.getContext(); 724 String[] apnArrayData = c.getResources().getStringArray(R.array.config_tether_apndata); 725 for (String apn : apnArrayData) { 726 ApnSetting dunSetting = ApnSetting.fromString(apn); 727 if (dunSetting != null) { 728 if (dunSetting.bearer != 0) { 729 if (bearer == -1) bearer = mPhone.getServiceState().getRilDataRadioTechnology(); 730 if (dunSetting.bearer != bearer) continue; 731 } 732 if (dunSetting.hasMvnoParams()) { 733 if (r != null && 734 mvnoMatches(r, dunSetting.mvnoType, dunSetting.mvnoMatchData)) { 735 if (VDBG) log("fetchDunApn: config_tether_apndata mvno dunSetting=" 736 + dunSetting); 737 return dunSetting; 738 } 739 } else { 740 retDunSetting = dunSetting; 741 } 742 } 743 } 744 745 if (VDBG) log("fetchDunApn: config_tether_apndata dunSetting=" + retDunSetting); 746 return retDunSetting; 747 } 748 hasMatchedTetherApnSetting()749 public boolean hasMatchedTetherApnSetting() { 750 ApnSetting matched = fetchDunApn(); 751 log("hasMatchedTetherApnSetting: APN=" + matched); 752 return matched != null; 753 } 754 getActiveApnTypes()755 public String[] getActiveApnTypes() { 756 String[] result; 757 if (mActiveApn != null) { 758 result = mActiveApn.types; 759 } else { 760 result = new String[1]; 761 result[0] = PhoneConstants.APN_TYPE_DEFAULT; 762 } 763 return result; 764 } 765 766 /** TODO: See if we can remove */ getActiveApnString(String apnType)767 public String getActiveApnString(String apnType) { 768 String result = null; 769 if (mActiveApn != null) { 770 result = mActiveApn.apn; 771 } 772 return result; 773 } 774 775 /** 776 * Modify {@link android.provider.Settings.Global#DATA_ROAMING} value. 777 */ setDataOnRoamingEnabled(boolean enabled)778 public void setDataOnRoamingEnabled(boolean enabled) { 779 final int phoneSubId = mPhone.getSubId(); 780 if (getDataOnRoamingEnabled() != enabled) { 781 int roaming = enabled ? 1 : 0; 782 783 // For single SIM phones, this is a per phone property. 784 if (TelephonyManager.getDefault().getSimCount() == 1) { 785 Settings.Global.putInt(mResolver, Settings.Global.DATA_ROAMING, roaming); 786 } else { 787 Settings.Global.putInt(mResolver, Settings.Global.DATA_ROAMING + phoneSubId, roaming); 788 } 789 790 mSubscriptionManager.setDataRoaming(roaming, phoneSubId); 791 // will trigger handleDataOnRoamingChange() through observer 792 if (DBG) { 793 log("setDataOnRoamingEnabled: set phoneSubId=" + phoneSubId 794 + " isRoaming=" + enabled); 795 } 796 } else { 797 if (DBG) { 798 log("setDataOnRoamingEnabled: unchanged phoneSubId=" + phoneSubId 799 + " isRoaming=" + enabled); 800 } 801 } 802 } 803 804 /** 805 * Return current {@link android.provider.Settings.Global#DATA_ROAMING} value. 806 */ getDataOnRoamingEnabled()807 public boolean getDataOnRoamingEnabled() { 808 boolean isDataRoamingEnabled = "true".equalsIgnoreCase(SystemProperties.get( 809 "ro.com.android.dataroaming", "false")); 810 final int phoneSubId = mPhone.getSubId(); 811 812 try { 813 // For single SIM phones, this is a per phone property. 814 if (TelephonyManager.getDefault().getSimCount() == 1) { 815 isDataRoamingEnabled = Settings.Global.getInt(mResolver, 816 Settings.Global.DATA_ROAMING, isDataRoamingEnabled ? 1 : 0) != 0; 817 } else { 818 isDataRoamingEnabled = TelephonyManager.getIntWithSubId(mResolver, 819 Settings.Global.DATA_ROAMING, phoneSubId) != 0; 820 } 821 } catch (SettingNotFoundException snfe) { 822 if (DBG) log("getDataOnRoamingEnabled: SettingNofFoundException snfe=" + snfe); 823 } 824 if (DBG) { 825 log("getDataOnRoamingEnabled: phoneSubId=" + phoneSubId + 826 " isDataRoamingEnabled=" + isDataRoamingEnabled); 827 } 828 return isDataRoamingEnabled; 829 } 830 831 /** 832 * Modify {@link android.provider.Settings.Global#MOBILE_DATA} value. 833 */ setDataEnabled(boolean enable)834 public void setDataEnabled(boolean enable) { 835 Message msg = obtainMessage(DctConstants.CMD_SET_USER_DATA_ENABLE); 836 msg.arg1 = enable ? 1 : 0; 837 if (DBG) log("setDataEnabled: sendMessage: enable=" + enable); 838 sendMessage(msg); 839 } 840 841 /** 842 * Return current {@link android.provider.Settings.Global#MOBILE_DATA} value. 843 */ getDataEnabled()844 public boolean getDataEnabled() { 845 boolean retVal = "true".equalsIgnoreCase(SystemProperties.get( 846 "ro.com.android.mobiledata", "true")); 847 try { 848 if (TelephonyManager.getDefault().getSimCount() == 1) { 849 retVal = Settings.Global.getInt(mResolver, Settings.Global.MOBILE_DATA, 850 retVal ? 1 : 0) != 0; 851 } else { 852 int phoneSubId = mPhone.getSubId(); 853 retVal = TelephonyManager.getIntWithSubId(mResolver, Settings.Global.MOBILE_DATA, 854 phoneSubId) != 0; 855 } 856 if (DBG) log("getDataEnabled: getIntWithSubId retVal=" + retVal); 857 } catch (SettingNotFoundException snfe) { 858 retVal = "true".equalsIgnoreCase( 859 SystemProperties.get("ro.com.android.mobiledata", "true")); 860 if (DBG) { 861 log("getDataEnabled: system property ro.com.android.mobiledata retVal=" + retVal); 862 } 863 } 864 return retVal; 865 } 866 867 // abstract methods restartRadio()868 protected abstract void restartRadio(); log(String s)869 protected abstract void log(String s); loge(String s)870 protected abstract void loge(String s); isDataAllowed()871 protected abstract boolean isDataAllowed(); isApnTypeAvailable(String type)872 protected abstract boolean isApnTypeAvailable(String type); getState(String apnType)873 public abstract DctConstants.State getState(String apnType); isProvisioningApn(String apnType)874 protected abstract boolean isProvisioningApn(String apnType); setState(DctConstants.State s)875 protected abstract void setState(DctConstants.State s); gotoIdleAndNotifyDataConnection(String reason)876 protected abstract void gotoIdleAndNotifyDataConnection(String reason); 877 onTrySetupData(String reason)878 protected abstract boolean onTrySetupData(String reason); onRoamingOff()879 protected abstract void onRoamingOff(); onRoamingOn()880 protected abstract void onRoamingOn(); onRadioAvailable()881 protected abstract void onRadioAvailable(); onRadioOffOrNotAvailable()882 protected abstract void onRadioOffOrNotAvailable(); onDataSetupComplete(AsyncResult ar)883 protected abstract void onDataSetupComplete(AsyncResult ar); onDataSetupCompleteError(AsyncResult ar)884 protected abstract void onDataSetupCompleteError(AsyncResult ar); onDisconnectDone(int connId, AsyncResult ar)885 protected abstract void onDisconnectDone(int connId, AsyncResult ar); onDisconnectDcRetrying(int connId, AsyncResult ar)886 protected abstract void onDisconnectDcRetrying(int connId, AsyncResult ar); onVoiceCallStarted()887 protected abstract void onVoiceCallStarted(); onVoiceCallEnded()888 protected abstract void onVoiceCallEnded(); onCleanUpConnection(boolean tearDown, int apnId, String reason)889 protected abstract void onCleanUpConnection(boolean tearDown, int apnId, String reason); onCleanUpAllConnections(String cause)890 protected abstract void onCleanUpAllConnections(String cause); isDataPossible(String apnType)891 public abstract boolean isDataPossible(String apnType); onUpdateIcc()892 protected abstract void onUpdateIcc(); completeConnection(ApnContext apnContext)893 protected abstract void completeConnection(ApnContext apnContext); setDataAllowed(boolean enable, Message response)894 public abstract void setDataAllowed(boolean enable, Message response); getPcscfAddress(String apnType)895 public abstract String[] getPcscfAddress(String apnType); setImsRegistrationState(boolean registered)896 public abstract void setImsRegistrationState(boolean registered); mvnoMatches(IccRecords r, String mvno_type, String mvno_match_data)897 protected abstract boolean mvnoMatches(IccRecords r, String mvno_type, String mvno_match_data); isPermanentFail(DcFailCause dcFailCause)898 protected abstract boolean isPermanentFail(DcFailCause dcFailCause); 899 900 @Override handleMessage(Message msg)901 public void handleMessage(Message msg) { 902 switch (msg.what) { 903 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { 904 log("DISCONNECTED_CONNECTED: msg=" + msg); 905 DcAsyncChannel dcac = (DcAsyncChannel) msg.obj; 906 mDataConnectionAcHashMap.remove(dcac.getDataConnectionIdSync()); 907 dcac.disconnected(); 908 break; 909 } 910 case DctConstants.EVENT_ENABLE_NEW_APN: 911 onEnableApn(msg.arg1, msg.arg2); 912 break; 913 914 case DctConstants.EVENT_TRY_SETUP_DATA: 915 String reason = null; 916 if (msg.obj instanceof String) { 917 reason = (String) msg.obj; 918 } 919 onTrySetupData(reason); 920 break; 921 922 case DctConstants.EVENT_DATA_STALL_ALARM: 923 onDataStallAlarm(msg.arg1); 924 break; 925 926 case DctConstants.EVENT_ROAMING_OFF: 927 onRoamingOff(); 928 break; 929 930 case DctConstants.EVENT_ROAMING_ON: 931 onRoamingOn(); 932 break; 933 934 case DctConstants.EVENT_RADIO_AVAILABLE: 935 onRadioAvailable(); 936 break; 937 938 case DctConstants.EVENT_RADIO_OFF_OR_NOT_AVAILABLE: 939 onRadioOffOrNotAvailable(); 940 break; 941 942 case DctConstants.EVENT_DATA_SETUP_COMPLETE: 943 mCidActive = msg.arg1; 944 onDataSetupComplete((AsyncResult) msg.obj); 945 break; 946 947 case DctConstants.EVENT_DATA_SETUP_COMPLETE_ERROR: 948 onDataSetupCompleteError((AsyncResult) msg.obj); 949 break; 950 951 case DctConstants.EVENT_DISCONNECT_DONE: 952 log("DataConnectionTracker.handleMessage: EVENT_DISCONNECT_DONE msg=" + msg); 953 onDisconnectDone(msg.arg1, (AsyncResult) msg.obj); 954 break; 955 956 case DctConstants.EVENT_DISCONNECT_DC_RETRYING: 957 log("DataConnectionTracker.handleMessage: EVENT_DISCONNECT_DC_RETRYING msg=" + msg); 958 onDisconnectDcRetrying(msg.arg1, (AsyncResult) msg.obj); 959 break; 960 961 case DctConstants.EVENT_VOICE_CALL_STARTED: 962 onVoiceCallStarted(); 963 break; 964 965 case DctConstants.EVENT_VOICE_CALL_ENDED: 966 onVoiceCallEnded(); 967 break; 968 969 case DctConstants.EVENT_CLEAN_UP_ALL_CONNECTIONS: { 970 onCleanUpAllConnections((String) msg.obj); 971 break; 972 } 973 case DctConstants.EVENT_CLEAN_UP_CONNECTION: { 974 boolean tearDown = (msg.arg1 == 0) ? false : true; 975 onCleanUpConnection(tearDown, msg.arg2, (String) msg.obj); 976 break; 977 } 978 case DctConstants.EVENT_SET_INTERNAL_DATA_ENABLE: { 979 boolean enabled = (msg.arg1 == DctConstants.ENABLED) ? true : false; 980 onSetInternalDataEnabled(enabled); 981 break; 982 } 983 case DctConstants.EVENT_RESET_DONE: { 984 if (DBG) log("EVENT_RESET_DONE"); 985 onResetDone((AsyncResult) msg.obj); 986 break; 987 } 988 case DctConstants.CMD_SET_USER_DATA_ENABLE: { 989 final boolean enabled = (msg.arg1 == DctConstants.ENABLED) ? true : false; 990 if (DBG) log("CMD_SET_USER_DATA_ENABLE enabled=" + enabled); 991 onSetUserDataEnabled(enabled); 992 break; 993 } 994 case DctConstants.CMD_SET_DEPENDENCY_MET: { 995 boolean met = (msg.arg1 == DctConstants.ENABLED) ? true : false; 996 if (DBG) log("CMD_SET_DEPENDENCY_MET met=" + met); 997 Bundle bundle = msg.getData(); 998 if (bundle != null) { 999 String apnType = (String)bundle.get(DctConstants.APN_TYPE_KEY); 1000 if (apnType != null) { 1001 onSetDependencyMet(apnType, met); 1002 } 1003 } 1004 break; 1005 } 1006 case DctConstants.CMD_SET_POLICY_DATA_ENABLE: { 1007 final boolean enabled = (msg.arg1 == DctConstants.ENABLED) ? true : false; 1008 onSetPolicyDataEnabled(enabled); 1009 break; 1010 } 1011 case DctConstants.CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA: { 1012 sEnableFailFastRefCounter += (msg.arg1 == DctConstants.ENABLED) ? 1 : -1; 1013 if (DBG) { 1014 log("CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA: " 1015 + " sEnableFailFastRefCounter=" + sEnableFailFastRefCounter); 1016 } 1017 if (sEnableFailFastRefCounter < 0) { 1018 final String s = "CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA: " 1019 + "sEnableFailFastRefCounter:" + sEnableFailFastRefCounter + " < 0"; 1020 loge(s); 1021 sEnableFailFastRefCounter = 0; 1022 } 1023 final boolean enabled = sEnableFailFastRefCounter > 0; 1024 if (DBG) { 1025 log("CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA: enabled=" + enabled 1026 + " sEnableFailFastRefCounter=" + sEnableFailFastRefCounter); 1027 } 1028 if (mFailFast != enabled) { 1029 mFailFast = enabled; 1030 mDataStallDetectionEnabled = !enabled; 1031 if (mDataStallDetectionEnabled 1032 && (getOverallState() == DctConstants.State.CONNECTED) 1033 && (!mInVoiceCall || 1034 mPhone.getServiceStateTracker() 1035 .isConcurrentVoiceAndDataAllowed())) { 1036 if (DBG) log("CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA: start data stall"); 1037 stopDataStallAlarm(); 1038 startDataStallAlarm(DATA_STALL_NOT_SUSPECTED); 1039 } else { 1040 if (DBG) log("CMD_SET_ENABLE_FAIL_FAST_MOBILE_DATA: stop data stall"); 1041 stopDataStallAlarm(); 1042 } 1043 } 1044 1045 break; 1046 } 1047 case DctConstants.CMD_ENABLE_MOBILE_PROVISIONING: { 1048 Bundle bundle = msg.getData(); 1049 if (bundle != null) { 1050 try { 1051 mProvisioningUrl = (String)bundle.get(DctConstants.PROVISIONING_URL_KEY); 1052 } catch(ClassCastException e) { 1053 loge("CMD_ENABLE_MOBILE_PROVISIONING: provisioning url not a string" + e); 1054 mProvisioningUrl = null; 1055 } 1056 } 1057 if (TextUtils.isEmpty(mProvisioningUrl)) { 1058 loge("CMD_ENABLE_MOBILE_PROVISIONING: provisioning url is empty, ignoring"); 1059 mIsProvisioning = false; 1060 mProvisioningUrl = null; 1061 } else { 1062 loge("CMD_ENABLE_MOBILE_PROVISIONING: provisioningUrl=" + mProvisioningUrl); 1063 mIsProvisioning = true; 1064 startProvisioningApnAlarm(); 1065 } 1066 break; 1067 } 1068 case DctConstants.EVENT_PROVISIONING_APN_ALARM: { 1069 if (DBG) log("EVENT_PROVISIONING_APN_ALARM"); 1070 ApnContext apnCtx = mApnContexts.get("default"); 1071 if (apnCtx.isProvisioningApn() && apnCtx.isConnectedOrConnecting()) { 1072 if (mProvisioningApnAlarmTag == msg.arg1) { 1073 if (DBG) log("EVENT_PROVISIONING_APN_ALARM: Disconnecting"); 1074 mIsProvisioning = false; 1075 mProvisioningUrl = null; 1076 stopProvisioningApnAlarm(); 1077 sendCleanUpConnection(true, apnCtx); 1078 } else { 1079 if (DBG) { 1080 log("EVENT_PROVISIONING_APN_ALARM: ignore stale tag," 1081 + " mProvisioningApnAlarmTag:" + mProvisioningApnAlarmTag 1082 + " != arg1:" + msg.arg1); 1083 } 1084 } 1085 } else { 1086 if (DBG) log("EVENT_PROVISIONING_APN_ALARM: Not connected ignore"); 1087 } 1088 break; 1089 } 1090 case DctConstants.CMD_IS_PROVISIONING_APN: { 1091 if (DBG) log("CMD_IS_PROVISIONING_APN"); 1092 boolean isProvApn; 1093 try { 1094 String apnType = null; 1095 Bundle bundle = msg.getData(); 1096 if (bundle != null) { 1097 apnType = (String)bundle.get(DctConstants.APN_TYPE_KEY); 1098 } 1099 if (TextUtils.isEmpty(apnType)) { 1100 loge("CMD_IS_PROVISIONING_APN: apnType is empty"); 1101 isProvApn = false; 1102 } else { 1103 isProvApn = isProvisioningApn(apnType); 1104 } 1105 } catch (ClassCastException e) { 1106 loge("CMD_IS_PROVISIONING_APN: NO provisioning url ignoring"); 1107 isProvApn = false; 1108 } 1109 if (DBG) log("CMD_IS_PROVISIONING_APN: ret=" + isProvApn); 1110 mReplyAc.replyToMessage(msg, DctConstants.CMD_IS_PROVISIONING_APN, 1111 isProvApn ? DctConstants.ENABLED : DctConstants.DISABLED); 1112 break; 1113 } 1114 case DctConstants.EVENT_ICC_CHANGED: { 1115 onUpdateIcc(); 1116 break; 1117 } 1118 case DctConstants.EVENT_RESTART_RADIO: { 1119 restartRadio(); 1120 break; 1121 } 1122 case DctConstants.CMD_NET_STAT_POLL: { 1123 if (msg.arg1 == DctConstants.ENABLED) { 1124 handleStartNetStatPoll((DctConstants.Activity)msg.obj); 1125 } else if (msg.arg1 == DctConstants.DISABLED) { 1126 handleStopNetStatPoll((DctConstants.Activity)msg.obj); 1127 } 1128 break; 1129 } 1130 default: 1131 Rlog.e("DATA", "Unidentified event msg=" + msg); 1132 break; 1133 } 1134 } 1135 1136 /** 1137 * Report on whether data connectivity is enabled 1138 * 1139 * @return {@code false} if data connectivity has been explicitly disabled, 1140 * {@code true} otherwise. 1141 */ getAnyDataEnabled()1142 public boolean getAnyDataEnabled() { 1143 final boolean result; 1144 synchronized (mDataEnabledLock) { 1145 result = (mInternalDataEnabled && mUserDataEnabled && sPolicyDataEnabled 1146 && (mEnabledCount != 0)); 1147 } 1148 if (!result && DBG) log("getAnyDataEnabled " + result); 1149 return result; 1150 } 1151 isEmergency()1152 protected boolean isEmergency() { 1153 final boolean result; 1154 synchronized (mDataEnabledLock) { 1155 result = mPhone.isInEcm() || mPhone.isInEmergencyCall(); 1156 } 1157 log("isEmergency: result=" + result); 1158 return result; 1159 } 1160 apnTypeToId(String type)1161 protected int apnTypeToId(String type) { 1162 if (TextUtils.equals(type, PhoneConstants.APN_TYPE_DEFAULT)) { 1163 return DctConstants.APN_DEFAULT_ID; 1164 } else if (TextUtils.equals(type, PhoneConstants.APN_TYPE_MMS)) { 1165 return DctConstants.APN_MMS_ID; 1166 } else if (TextUtils.equals(type, PhoneConstants.APN_TYPE_SUPL)) { 1167 return DctConstants.APN_SUPL_ID; 1168 } else if (TextUtils.equals(type, PhoneConstants.APN_TYPE_DUN)) { 1169 return DctConstants.APN_DUN_ID; 1170 } else if (TextUtils.equals(type, PhoneConstants.APN_TYPE_HIPRI)) { 1171 return DctConstants.APN_HIPRI_ID; 1172 } else if (TextUtils.equals(type, PhoneConstants.APN_TYPE_IMS)) { 1173 return DctConstants.APN_IMS_ID; 1174 } else if (TextUtils.equals(type, PhoneConstants.APN_TYPE_FOTA)) { 1175 return DctConstants.APN_FOTA_ID; 1176 } else if (TextUtils.equals(type, PhoneConstants.APN_TYPE_CBS)) { 1177 return DctConstants.APN_CBS_ID; 1178 } else if (TextUtils.equals(type, PhoneConstants.APN_TYPE_IA)) { 1179 return DctConstants.APN_IA_ID; 1180 } else if (TextUtils.equals(type, PhoneConstants.APN_TYPE_EMERGENCY)) { 1181 return DctConstants.APN_EMERGENCY_ID; 1182 } else { 1183 return DctConstants.APN_INVALID_ID; 1184 } 1185 } 1186 apnIdToType(int id)1187 protected String apnIdToType(int id) { 1188 switch (id) { 1189 case DctConstants.APN_DEFAULT_ID: 1190 return PhoneConstants.APN_TYPE_DEFAULT; 1191 case DctConstants.APN_MMS_ID: 1192 return PhoneConstants.APN_TYPE_MMS; 1193 case DctConstants.APN_SUPL_ID: 1194 return PhoneConstants.APN_TYPE_SUPL; 1195 case DctConstants.APN_DUN_ID: 1196 return PhoneConstants.APN_TYPE_DUN; 1197 case DctConstants.APN_HIPRI_ID: 1198 return PhoneConstants.APN_TYPE_HIPRI; 1199 case DctConstants.APN_IMS_ID: 1200 return PhoneConstants.APN_TYPE_IMS; 1201 case DctConstants.APN_FOTA_ID: 1202 return PhoneConstants.APN_TYPE_FOTA; 1203 case DctConstants.APN_CBS_ID: 1204 return PhoneConstants.APN_TYPE_CBS; 1205 case DctConstants.APN_IA_ID: 1206 return PhoneConstants.APN_TYPE_IA; 1207 case DctConstants.APN_EMERGENCY_ID: 1208 return PhoneConstants.APN_TYPE_EMERGENCY; 1209 default: 1210 log("Unknown id (" + id + ") in apnIdToType"); 1211 return PhoneConstants.APN_TYPE_DEFAULT; 1212 } 1213 } 1214 getLinkProperties(String apnType)1215 public LinkProperties getLinkProperties(String apnType) { 1216 int id = apnTypeToId(apnType); 1217 1218 if (isApnIdEnabled(id)) { 1219 DcAsyncChannel dcac = mDataConnectionAcHashMap.get(0); 1220 return dcac.getLinkPropertiesSync(); 1221 } else { 1222 return new LinkProperties(); 1223 } 1224 } 1225 getNetworkCapabilities(String apnType)1226 public NetworkCapabilities getNetworkCapabilities(String apnType) { 1227 int id = apnTypeToId(apnType); 1228 if (isApnIdEnabled(id)) { 1229 DcAsyncChannel dcac = mDataConnectionAcHashMap.get(0); 1230 return dcac.getNetworkCapabilitiesSync(); 1231 } else { 1232 return new NetworkCapabilities(); 1233 } 1234 } 1235 1236 // tell all active apns of the current condition notifyDataConnection(String reason)1237 protected void notifyDataConnection(String reason) { 1238 for (int id = 0; id < DctConstants.APN_NUM_TYPES; id++) { 1239 if (mDataEnabled[id]) { 1240 mPhone.notifyDataConnection(reason, apnIdToType(id)); 1241 } 1242 } 1243 notifyOffApnsOfAvailability(reason); 1244 } 1245 1246 // a new APN has gone active and needs to send events to catch up with the 1247 // current condition notifyApnIdUpToCurrent(String reason, int apnId)1248 private void notifyApnIdUpToCurrent(String reason, int apnId) { 1249 switch (mState) { 1250 case IDLE: 1251 break; 1252 case RETRYING: 1253 case CONNECTING: 1254 case SCANNING: 1255 mPhone.notifyDataConnection(reason, apnIdToType(apnId), 1256 PhoneConstants.DataState.CONNECTING); 1257 break; 1258 case CONNECTED: 1259 case DISCONNECTING: 1260 mPhone.notifyDataConnection(reason, apnIdToType(apnId), 1261 PhoneConstants.DataState.CONNECTING); 1262 mPhone.notifyDataConnection(reason, apnIdToType(apnId), 1263 PhoneConstants.DataState.CONNECTED); 1264 break; 1265 default: 1266 // Ignore 1267 break; 1268 } 1269 } 1270 1271 // since we normally don't send info to a disconnected APN, we need to do this specially notifyApnIdDisconnected(String reason, int apnId)1272 private void notifyApnIdDisconnected(String reason, int apnId) { 1273 mPhone.notifyDataConnection(reason, apnIdToType(apnId), 1274 PhoneConstants.DataState.DISCONNECTED); 1275 } 1276 1277 // disabled apn's still need avail/unavail notificiations - send them out notifyOffApnsOfAvailability(String reason)1278 protected void notifyOffApnsOfAvailability(String reason) { 1279 if (DBG) log("notifyOffApnsOfAvailability - reason= " + reason); 1280 for (int id = 0; id < DctConstants.APN_NUM_TYPES; id++) { 1281 if (!isApnIdEnabled(id)) { 1282 notifyApnIdDisconnected(reason, id); 1283 } 1284 } 1285 } 1286 isApnTypeEnabled(String apnType)1287 public boolean isApnTypeEnabled(String apnType) { 1288 if (apnType == null) { 1289 return false; 1290 } else { 1291 return isApnIdEnabled(apnTypeToId(apnType)); 1292 } 1293 } 1294 isApnIdEnabled(int id)1295 protected synchronized boolean isApnIdEnabled(int id) { 1296 if (id != DctConstants.APN_INVALID_ID) { 1297 return mDataEnabled[id]; 1298 } 1299 return false; 1300 } 1301 setEnabled(int id, boolean enable)1302 protected void setEnabled(int id, boolean enable) { 1303 if (DBG) { 1304 log("setEnabled(" + id + ", " + enable + ") with old state = " + mDataEnabled[id] 1305 + " and enabledCount = " + mEnabledCount); 1306 } 1307 Message msg = obtainMessage(DctConstants.EVENT_ENABLE_NEW_APN); 1308 msg.arg1 = id; 1309 msg.arg2 = (enable ? DctConstants.ENABLED : DctConstants.DISABLED); 1310 sendMessage(msg); 1311 } 1312 onEnableApn(int apnId, int enabled)1313 protected void onEnableApn(int apnId, int enabled) { 1314 if (DBG) { 1315 log("EVENT_APN_ENABLE_REQUEST apnId=" + apnId + ", apnType=" + apnIdToType(apnId) + 1316 ", enabled=" + enabled + ", dataEnabled = " + mDataEnabled[apnId] + 1317 ", enabledCount = " + mEnabledCount + ", isApnTypeActive = " + 1318 isApnTypeActive(apnIdToType(apnId))); 1319 } 1320 if (enabled == DctConstants.ENABLED) { 1321 synchronized (this) { 1322 if (!mDataEnabled[apnId]) { 1323 mDataEnabled[apnId] = true; 1324 mEnabledCount++; 1325 } 1326 } 1327 String type = apnIdToType(apnId); 1328 if (!isApnTypeActive(type)) { 1329 mRequestedApnType = type; 1330 onEnableNewApn(); 1331 } else { 1332 notifyApnIdUpToCurrent(Phone.REASON_APN_SWITCHED, apnId); 1333 } 1334 } else { 1335 // disable 1336 boolean didDisable = false; 1337 synchronized (this) { 1338 if (mDataEnabled[apnId]) { 1339 mDataEnabled[apnId] = false; 1340 mEnabledCount--; 1341 didDisable = true; 1342 } 1343 } 1344 if (didDisable) { 1345 if ((mEnabledCount == 0) || (apnId == DctConstants.APN_DUN_ID)) { 1346 mRequestedApnType = PhoneConstants.APN_TYPE_DEFAULT; 1347 onCleanUpConnection(true, apnId, Phone.REASON_DATA_DISABLED); 1348 } 1349 1350 // send the disconnect msg manually, since the normal route wont send 1351 // it (it's not enabled) 1352 notifyApnIdDisconnected(Phone.REASON_DATA_DISABLED, apnId); 1353 if (mDataEnabled[DctConstants.APN_DEFAULT_ID] == true 1354 && !isApnTypeActive(PhoneConstants.APN_TYPE_DEFAULT)) { 1355 // TODO - this is an ugly way to restore the default conn - should be done 1356 // by a real contention manager and policy that disconnects the lower pri 1357 // stuff as enable requests come in and pops them back on as we disable back 1358 // down to the lower pri stuff 1359 mRequestedApnType = PhoneConstants.APN_TYPE_DEFAULT; 1360 onEnableNewApn(); 1361 } 1362 } 1363 } 1364 } 1365 1366 /** 1367 * Called when we switch APNs. 1368 * 1369 * mRequestedApnType is set prior to call 1370 * To be overridden. 1371 */ onEnableNewApn()1372 protected void onEnableNewApn() { 1373 } 1374 1375 /** 1376 * Called when EVENT_RESET_DONE is received so goto 1377 * IDLE state and send notifications to those interested. 1378 * 1379 * TODO - currently unused. Needs to be hooked into DataConnection cleanup 1380 * TODO - needs to pass some notion of which connection is reset.. 1381 */ onResetDone(AsyncResult ar)1382 protected void onResetDone(AsyncResult ar) { 1383 if (DBG) log("EVENT_RESET_DONE"); 1384 String reason = null; 1385 if (ar.userObj instanceof String) { 1386 reason = (String) ar.userObj; 1387 } 1388 gotoIdleAndNotifyDataConnection(reason); 1389 } 1390 1391 /** 1392 * Prevent mobile data connections from being established, or once again 1393 * allow mobile data connections. If the state toggles, then either tear 1394 * down or set up data, as appropriate to match the new state. 1395 * 1396 * @param enable indicates whether to enable ({@code true}) or disable ( 1397 * {@code false}) data 1398 * @return {@code true} if the operation succeeded 1399 */ setInternalDataEnabled(boolean enable)1400 public boolean setInternalDataEnabled(boolean enable) { 1401 if (DBG) 1402 log("setInternalDataEnabled(" + enable + ")"); 1403 1404 Message msg = obtainMessage(DctConstants.EVENT_SET_INTERNAL_DATA_ENABLE); 1405 msg.arg1 = (enable ? DctConstants.ENABLED : DctConstants.DISABLED); 1406 sendMessage(msg); 1407 return true; 1408 } 1409 onSetInternalDataEnabled(boolean enabled)1410 protected void onSetInternalDataEnabled(boolean enabled) { 1411 synchronized (mDataEnabledLock) { 1412 mInternalDataEnabled = enabled; 1413 if (enabled) { 1414 log("onSetInternalDataEnabled: changed to enabled, try to setup data call"); 1415 onTrySetupData(Phone.REASON_DATA_ENABLED); 1416 } else { 1417 log("onSetInternalDataEnabled: changed to disabled, cleanUpAllConnections"); 1418 cleanUpAllConnections(null); 1419 } 1420 } 1421 } 1422 cleanUpAllConnections(String cause)1423 public void cleanUpAllConnections(String cause) { 1424 Message msg = obtainMessage(DctConstants.EVENT_CLEAN_UP_ALL_CONNECTIONS); 1425 msg.obj = cause; 1426 sendMessage(msg); 1427 } 1428 isDisconnected()1429 public abstract boolean isDisconnected(); 1430 onSetUserDataEnabled(boolean enabled)1431 protected void onSetUserDataEnabled(boolean enabled) { 1432 synchronized (mDataEnabledLock) { 1433 if (mUserDataEnabled != enabled) { 1434 mUserDataEnabled = enabled; 1435 1436 // For single SIM phones, this is a per phone property. 1437 if (TelephonyManager.getDefault().getSimCount() == 1) { 1438 Settings.Global.putInt(mResolver, Settings.Global.MOBILE_DATA, enabled ? 1 : 0); 1439 } else { 1440 int phoneSubId = mPhone.getSubId(); 1441 Settings.Global.putInt(mResolver, Settings.Global.MOBILE_DATA + phoneSubId, 1442 enabled ? 1 : 0); 1443 } 1444 if (getDataOnRoamingEnabled() == false && 1445 mPhone.getServiceState().getDataRoaming() == true) { 1446 if (enabled) { 1447 notifyOffApnsOfAvailability(Phone.REASON_ROAMING_ON); 1448 } else { 1449 notifyOffApnsOfAvailability(Phone.REASON_DATA_DISABLED); 1450 } 1451 } 1452 1453 if (enabled) { 1454 onTrySetupData(Phone.REASON_DATA_ENABLED); 1455 } else { 1456 onCleanUpAllConnections(Phone.REASON_DATA_SPECIFIC_DISABLED); 1457 } 1458 } 1459 } 1460 } 1461 onSetDependencyMet(String apnType, boolean met)1462 protected void onSetDependencyMet(String apnType, boolean met) { 1463 } 1464 onSetPolicyDataEnabled(boolean enabled)1465 protected void onSetPolicyDataEnabled(boolean enabled) { 1466 synchronized (mDataEnabledLock) { 1467 final boolean prevEnabled = getAnyDataEnabled(); 1468 if (sPolicyDataEnabled != enabled) { 1469 sPolicyDataEnabled = enabled; 1470 if (prevEnabled != getAnyDataEnabled()) { 1471 if (!prevEnabled) { 1472 onTrySetupData(Phone.REASON_DATA_ENABLED); 1473 } else { 1474 onCleanUpAllConnections(Phone.REASON_DATA_SPECIFIC_DISABLED); 1475 } 1476 } 1477 } 1478 } 1479 } 1480 getReryConfig(boolean forDefault)1481 protected String getReryConfig(boolean forDefault) { 1482 int nt = mPhone.getServiceState().getNetworkType(); 1483 1484 if ((nt == TelephonyManager.NETWORK_TYPE_CDMA) || 1485 (nt == TelephonyManager.NETWORK_TYPE_1xRTT) || 1486 (nt == TelephonyManager.NETWORK_TYPE_EVDO_0) || 1487 (nt == TelephonyManager.NETWORK_TYPE_EVDO_A) || 1488 (nt == TelephonyManager.NETWORK_TYPE_EVDO_B) || 1489 (nt == TelephonyManager.NETWORK_TYPE_EHRPD)) { 1490 // CDMA variant 1491 return SystemProperties.get("ro.cdma.data_retry_config"); 1492 } else { 1493 // Use GSM varient for all others. 1494 if (forDefault) { 1495 return SystemProperties.get("ro.gsm.data_retry_config"); 1496 } else { 1497 return SystemProperties.get("ro.gsm.2nd_data_retry_config"); 1498 } 1499 } 1500 } 1501 resetPollStats()1502 protected void resetPollStats() { 1503 mTxPkts = -1; 1504 mRxPkts = -1; 1505 mNetStatPollPeriod = POLL_NETSTAT_MILLIS; 1506 } 1507 getOverallState()1508 protected abstract DctConstants.State getOverallState(); 1509 startNetStatPoll()1510 void startNetStatPoll() { 1511 if (getOverallState() == DctConstants.State.CONNECTED 1512 && mNetStatPollEnabled == false) { 1513 if (DBG) { 1514 log("startNetStatPoll"); 1515 } 1516 resetPollStats(); 1517 mNetStatPollEnabled = true; 1518 mPollNetStat.run(); 1519 } 1520 if (mPhone != null) { 1521 mPhone.notifyDataActivity(); 1522 } 1523 } 1524 stopNetStatPoll()1525 void stopNetStatPoll() { 1526 mNetStatPollEnabled = false; 1527 removeCallbacks(mPollNetStat); 1528 if (DBG) { 1529 log("stopNetStatPoll"); 1530 } 1531 1532 // To sync data activity icon in the case of switching data connection to send MMS. 1533 if (mPhone != null) { 1534 mPhone.notifyDataActivity(); 1535 } 1536 } 1537 sendStartNetStatPoll(DctConstants.Activity activity)1538 public void sendStartNetStatPoll(DctConstants.Activity activity) { 1539 Message msg = obtainMessage(DctConstants.CMD_NET_STAT_POLL); 1540 msg.arg1 = DctConstants.ENABLED; 1541 msg.obj = activity; 1542 sendMessage(msg); 1543 } 1544 handleStartNetStatPoll(DctConstants.Activity activity)1545 protected void handleStartNetStatPoll(DctConstants.Activity activity) { 1546 startNetStatPoll(); 1547 startDataStallAlarm(DATA_STALL_NOT_SUSPECTED); 1548 setActivity(activity); 1549 } 1550 sendStopNetStatPoll(DctConstants.Activity activity)1551 public void sendStopNetStatPoll(DctConstants.Activity activity) { 1552 Message msg = obtainMessage(DctConstants.CMD_NET_STAT_POLL); 1553 msg.arg1 = DctConstants.DISABLED; 1554 msg.obj = activity; 1555 sendMessage(msg); 1556 } 1557 handleStopNetStatPoll(DctConstants.Activity activity)1558 protected void handleStopNetStatPoll(DctConstants.Activity activity) { 1559 stopNetStatPoll(); 1560 stopDataStallAlarm(); 1561 setActivity(activity); 1562 } 1563 updateDataActivity()1564 public void updateDataActivity() { 1565 long sent, received; 1566 1567 DctConstants.Activity newActivity; 1568 1569 TxRxSum preTxRxSum = new TxRxSum(mTxPkts, mRxPkts); 1570 TxRxSum curTxRxSum = new TxRxSum(); 1571 curTxRxSum.updateTxRxSum(); 1572 mTxPkts = curTxRxSum.txPkts; 1573 mRxPkts = curTxRxSum.rxPkts; 1574 1575 if (VDBG) { 1576 log("updateDataActivity: curTxRxSum=" + curTxRxSum + " preTxRxSum=" + preTxRxSum); 1577 } 1578 1579 if (mNetStatPollEnabled && (preTxRxSum.txPkts > 0 || preTxRxSum.rxPkts > 0)) { 1580 sent = mTxPkts - preTxRxSum.txPkts; 1581 received = mRxPkts - preTxRxSum.rxPkts; 1582 1583 if (VDBG) 1584 log("updateDataActivity: sent=" + sent + " received=" + received); 1585 if (sent > 0 && received > 0) { 1586 newActivity = DctConstants.Activity.DATAINANDOUT; 1587 } else if (sent > 0 && received == 0) { 1588 newActivity = DctConstants.Activity.DATAOUT; 1589 } else if (sent == 0 && received > 0) { 1590 newActivity = DctConstants.Activity.DATAIN; 1591 } else { 1592 newActivity = (mActivity == DctConstants.Activity.DORMANT) ? 1593 mActivity : DctConstants.Activity.NONE; 1594 } 1595 1596 if (mActivity != newActivity && mIsScreenOn) { 1597 if (VDBG) 1598 log("updateDataActivity: newActivity=" + newActivity); 1599 mActivity = newActivity; 1600 mPhone.notifyDataActivity(); 1601 } 1602 } 1603 } 1604 1605 // Recovery action taken in case of data stall 1606 protected static class RecoveryAction { 1607 public static final int GET_DATA_CALL_LIST = 0; 1608 public static final int CLEANUP = 1; 1609 public static final int REREGISTER = 2; 1610 public static final int RADIO_RESTART = 3; 1611 public static final int RADIO_RESTART_WITH_PROP = 4; 1612 isAggressiveRecovery(int value)1613 private static boolean isAggressiveRecovery(int value) { 1614 return ((value == RecoveryAction.CLEANUP) || 1615 (value == RecoveryAction.REREGISTER) || 1616 (value == RecoveryAction.RADIO_RESTART) || 1617 (value == RecoveryAction.RADIO_RESTART_WITH_PROP)); 1618 } 1619 } 1620 getRecoveryAction()1621 public int getRecoveryAction() { 1622 int action = Settings.System.getInt(mResolver, 1623 "radio.data.stall.recovery.action", RecoveryAction.GET_DATA_CALL_LIST); 1624 if (VDBG_STALL) log("getRecoveryAction: " + action); 1625 return action; 1626 } putRecoveryAction(int action)1627 public void putRecoveryAction(int action) { 1628 Settings.System.putInt(mResolver, "radio.data.stall.recovery.action", action); 1629 if (VDBG_STALL) log("putRecoveryAction: " + action); 1630 } 1631 isConnected()1632 protected boolean isConnected() { 1633 return false; 1634 } 1635 doRecovery()1636 protected void doRecovery() { 1637 if (getOverallState() == DctConstants.State.CONNECTED) { 1638 // Go through a series of recovery steps, each action transitions to the next action 1639 int recoveryAction = getRecoveryAction(); 1640 switch (recoveryAction) { 1641 case RecoveryAction.GET_DATA_CALL_LIST: 1642 EventLog.writeEvent(EventLogTags.DATA_STALL_RECOVERY_GET_DATA_CALL_LIST, 1643 mSentSinceLastRecv); 1644 if (DBG) log("doRecovery() get data call list"); 1645 mPhone.mCi.getDataCallList(obtainMessage(DctConstants.EVENT_DATA_STATE_CHANGED)); 1646 putRecoveryAction(RecoveryAction.CLEANUP); 1647 break; 1648 case RecoveryAction.CLEANUP: 1649 EventLog.writeEvent(EventLogTags.DATA_STALL_RECOVERY_CLEANUP, mSentSinceLastRecv); 1650 if (DBG) log("doRecovery() cleanup all connections"); 1651 cleanUpAllConnections(Phone.REASON_PDP_RESET); 1652 putRecoveryAction(RecoveryAction.REREGISTER); 1653 break; 1654 case RecoveryAction.REREGISTER: 1655 EventLog.writeEvent(EventLogTags.DATA_STALL_RECOVERY_REREGISTER, 1656 mSentSinceLastRecv); 1657 if (DBG) log("doRecovery() re-register"); 1658 mPhone.getServiceStateTracker().reRegisterNetwork(null); 1659 putRecoveryAction(RecoveryAction.RADIO_RESTART); 1660 break; 1661 case RecoveryAction.RADIO_RESTART: 1662 EventLog.writeEvent(EventLogTags.DATA_STALL_RECOVERY_RADIO_RESTART, 1663 mSentSinceLastRecv); 1664 if (DBG) log("restarting radio"); 1665 putRecoveryAction(RecoveryAction.RADIO_RESTART_WITH_PROP); 1666 restartRadio(); 1667 break; 1668 case RecoveryAction.RADIO_RESTART_WITH_PROP: 1669 // This is in case radio restart has not recovered the data. 1670 // It will set an additional "gsm.radioreset" property to tell 1671 // RIL or system to take further action. 1672 // The implementation of hard reset recovery action is up to OEM product. 1673 // Once RADIO_RESET property is consumed, it is expected to set back 1674 // to false by RIL. 1675 EventLog.writeEvent(EventLogTags.DATA_STALL_RECOVERY_RADIO_RESTART_WITH_PROP, -1); 1676 if (DBG) log("restarting radio with gsm.radioreset to true"); 1677 SystemProperties.set(RADIO_RESET_PROPERTY, "true"); 1678 // give 1 sec so property change can be notified. 1679 try { 1680 Thread.sleep(1000); 1681 } catch (InterruptedException e) {} 1682 restartRadio(); 1683 putRecoveryAction(RecoveryAction.GET_DATA_CALL_LIST); 1684 break; 1685 default: 1686 throw new RuntimeException("doRecovery: Invalid recoveryAction=" + 1687 recoveryAction); 1688 } 1689 mSentSinceLastRecv = 0; 1690 } 1691 } 1692 updateDataStallInfo()1693 private void updateDataStallInfo() { 1694 long sent, received; 1695 1696 TxRxSum preTxRxSum = new TxRxSum(mDataStallTxRxSum); 1697 mDataStallTxRxSum.updateTxRxSum(); 1698 1699 if (VDBG_STALL) { 1700 log("updateDataStallInfo: mDataStallTxRxSum=" + mDataStallTxRxSum + 1701 " preTxRxSum=" + preTxRxSum); 1702 } 1703 1704 sent = mDataStallTxRxSum.txPkts - preTxRxSum.txPkts; 1705 received = mDataStallTxRxSum.rxPkts - preTxRxSum.rxPkts; 1706 1707 if (RADIO_TESTS) { 1708 if (SystemProperties.getBoolean("radio.test.data.stall", false)) { 1709 log("updateDataStallInfo: radio.test.data.stall true received = 0;"); 1710 received = 0; 1711 } 1712 } 1713 if ( sent > 0 && received > 0 ) { 1714 if (VDBG_STALL) log("updateDataStallInfo: IN/OUT"); 1715 mSentSinceLastRecv = 0; 1716 putRecoveryAction(RecoveryAction.GET_DATA_CALL_LIST); 1717 } else if (sent > 0 && received == 0) { 1718 if (mPhone.getState() == PhoneConstants.State.IDLE) { 1719 mSentSinceLastRecv += sent; 1720 } else { 1721 mSentSinceLastRecv = 0; 1722 } 1723 if (DBG) { 1724 log("updateDataStallInfo: OUT sent=" + sent + 1725 " mSentSinceLastRecv=" + mSentSinceLastRecv); 1726 } 1727 } else if (sent == 0 && received > 0) { 1728 if (VDBG_STALL) log("updateDataStallInfo: IN"); 1729 mSentSinceLastRecv = 0; 1730 putRecoveryAction(RecoveryAction.GET_DATA_CALL_LIST); 1731 } else { 1732 if (VDBG_STALL) log("updateDataStallInfo: NONE"); 1733 } 1734 } 1735 onDataStallAlarm(int tag)1736 protected void onDataStallAlarm(int tag) { 1737 if (mDataStallAlarmTag != tag) { 1738 if (DBG) { 1739 log("onDataStallAlarm: ignore, tag=" + tag + " expecting " + mDataStallAlarmTag); 1740 } 1741 return; 1742 } 1743 updateDataStallInfo(); 1744 1745 int hangWatchdogTrigger = Settings.Global.getInt(mResolver, 1746 Settings.Global.PDP_WATCHDOG_TRIGGER_PACKET_COUNT, 1747 NUMBER_SENT_PACKETS_OF_HANG); 1748 1749 boolean suspectedStall = DATA_STALL_NOT_SUSPECTED; 1750 if (mSentSinceLastRecv >= hangWatchdogTrigger) { 1751 if (DBG) { 1752 log("onDataStallAlarm: tag=" + tag + " do recovery action=" + getRecoveryAction()); 1753 } 1754 suspectedStall = DATA_STALL_SUSPECTED; 1755 sendMessage(obtainMessage(DctConstants.EVENT_DO_RECOVERY)); 1756 } else { 1757 if (VDBG_STALL) { 1758 log("onDataStallAlarm: tag=" + tag + " Sent " + String.valueOf(mSentSinceLastRecv) + 1759 " pkts since last received, < watchdogTrigger=" + hangWatchdogTrigger); 1760 } 1761 } 1762 startDataStallAlarm(suspectedStall); 1763 } 1764 startDataStallAlarm(boolean suspectedStall)1765 protected void startDataStallAlarm(boolean suspectedStall) { 1766 int nextAction = getRecoveryAction(); 1767 int delayInMs; 1768 1769 if (mDataStallDetectionEnabled && getOverallState() == DctConstants.State.CONNECTED) { 1770 // If screen is on or data stall is currently suspected, set the alarm 1771 // with an aggresive timeout. 1772 if (mIsScreenOn || suspectedStall || RecoveryAction.isAggressiveRecovery(nextAction)) { 1773 delayInMs = Settings.Global.getInt(mResolver, 1774 Settings.Global.DATA_STALL_ALARM_AGGRESSIVE_DELAY_IN_MS, 1775 DATA_STALL_ALARM_AGGRESSIVE_DELAY_IN_MS_DEFAULT); 1776 } else { 1777 delayInMs = Settings.Global.getInt(mResolver, 1778 Settings.Global.DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS, 1779 DATA_STALL_ALARM_NON_AGGRESSIVE_DELAY_IN_MS_DEFAULT); 1780 } 1781 1782 mDataStallAlarmTag += 1; 1783 if (VDBG_STALL) { 1784 log("startDataStallAlarm: tag=" + mDataStallAlarmTag + 1785 " delay=" + (delayInMs / 1000) + "s"); 1786 } 1787 Intent intent = new Intent(INTENT_DATA_STALL_ALARM); 1788 intent.putExtra(DATA_STALL_ALARM_TAG_EXTRA, mDataStallAlarmTag); 1789 mDataStallAlarmIntent = PendingIntent.getBroadcast(mPhone.getContext(), 0, intent, 1790 PendingIntent.FLAG_UPDATE_CURRENT); 1791 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1792 SystemClock.elapsedRealtime() + delayInMs, mDataStallAlarmIntent); 1793 } else { 1794 if (VDBG_STALL) { 1795 log("startDataStallAlarm: NOT started, no connection tag=" + mDataStallAlarmTag); 1796 } 1797 } 1798 } 1799 stopDataStallAlarm()1800 protected void stopDataStallAlarm() { 1801 if (VDBG_STALL) { 1802 log("stopDataStallAlarm: current tag=" + mDataStallAlarmTag + 1803 " mDataStallAlarmIntent=" + mDataStallAlarmIntent); 1804 } 1805 mDataStallAlarmTag += 1; 1806 if (mDataStallAlarmIntent != null) { 1807 mAlarmManager.cancel(mDataStallAlarmIntent); 1808 mDataStallAlarmIntent = null; 1809 } 1810 } 1811 restartDataStallAlarm()1812 protected void restartDataStallAlarm() { 1813 if (isConnected() == false) return; 1814 // To be called on screen status change. 1815 // Do not cancel the alarm if it is set with aggressive timeout. 1816 int nextAction = getRecoveryAction(); 1817 1818 if (RecoveryAction.isAggressiveRecovery(nextAction)) { 1819 if (DBG) log("restartDataStallAlarm: action is pending. not resetting the alarm."); 1820 return; 1821 } 1822 if (VDBG_STALL) log("restartDataStallAlarm: stop then start."); 1823 stopDataStallAlarm(); 1824 startDataStallAlarm(DATA_STALL_NOT_SUSPECTED); 1825 } 1826 setInitialAttachApn()1827 protected void setInitialAttachApn() { 1828 ApnSetting iaApnSetting = null; 1829 ApnSetting defaultApnSetting = null; 1830 ApnSetting firstApnSetting = null; 1831 1832 log("setInitialApn: E mPreferredApn=" + mPreferredApn); 1833 1834 if (mAllApnSettings != null && !mAllApnSettings.isEmpty()) { 1835 firstApnSetting = mAllApnSettings.get(0); 1836 log("setInitialApn: firstApnSetting=" + firstApnSetting); 1837 1838 // Search for Initial APN setting and the first apn that can handle default 1839 for (ApnSetting apn : mAllApnSettings) { 1840 // Can't use apn.canHandleType(), as that returns true for APNs that have no type. 1841 if (ArrayUtils.contains(apn.types, PhoneConstants.APN_TYPE_IA) && 1842 apn.carrierEnabled) { 1843 // The Initial Attach APN is highest priority so use it if there is one 1844 log("setInitialApn: iaApnSetting=" + apn); 1845 iaApnSetting = apn; 1846 break; 1847 } else if ((defaultApnSetting == null) 1848 && (apn.canHandleType(PhoneConstants.APN_TYPE_DEFAULT))) { 1849 // Use the first default apn if no better choice 1850 log("setInitialApn: defaultApnSetting=" + apn); 1851 defaultApnSetting = apn; 1852 } 1853 } 1854 } 1855 1856 // The priority of apn candidates from highest to lowest is: 1857 // 1) APN_TYPE_IA (Inital Attach) 1858 // 2) mPreferredApn, i.e. the current preferred apn 1859 // 3) The first apn that than handle APN_TYPE_DEFAULT 1860 // 4) The first APN we can find. 1861 1862 ApnSetting initialAttachApnSetting = null; 1863 if (iaApnSetting != null) { 1864 if (DBG) log("setInitialAttachApn: using iaApnSetting"); 1865 initialAttachApnSetting = iaApnSetting; 1866 } else if (mPreferredApn != null) { 1867 if (DBG) log("setInitialAttachApn: using mPreferredApn"); 1868 initialAttachApnSetting = mPreferredApn; 1869 } else if (defaultApnSetting != null) { 1870 if (DBG) log("setInitialAttachApn: using defaultApnSetting"); 1871 initialAttachApnSetting = defaultApnSetting; 1872 } else if (firstApnSetting != null) { 1873 if (DBG) log("setInitialAttachApn: using firstApnSetting"); 1874 initialAttachApnSetting = firstApnSetting; 1875 } 1876 1877 if (initialAttachApnSetting == null) { 1878 if (DBG) log("setInitialAttachApn: X There in no available apn"); 1879 } else { 1880 if (DBG) log("setInitialAttachApn: X selected Apn=" + initialAttachApnSetting); 1881 1882 mPhone.mCi.setInitialAttachApn(initialAttachApnSetting.apn, 1883 initialAttachApnSetting.protocol, initialAttachApnSetting.authType, 1884 initialAttachApnSetting.user, initialAttachApnSetting.password, null); 1885 } 1886 } 1887 setDataProfilesAsNeeded()1888 protected void setDataProfilesAsNeeded() { 1889 if (DBG) log("setDataProfilesAsNeeded"); 1890 if (mAllApnSettings != null && !mAllApnSettings.isEmpty()) { 1891 ArrayList<DataProfile> dps = new ArrayList<DataProfile>(); 1892 for (ApnSetting apn : mAllApnSettings) { 1893 if (apn.modemCognitive) { 1894 DataProfile dp = new DataProfile(apn, 1895 mPhone.getServiceState().getDataRoaming()); 1896 boolean isDup = false; 1897 for(DataProfile dpIn : dps) { 1898 if (dp.equals(dpIn)) { 1899 isDup = true; 1900 break; 1901 } 1902 } 1903 if (!isDup) { 1904 dps.add(dp); 1905 } 1906 } 1907 } 1908 if(dps.size() > 0) { 1909 mPhone.mCi.setDataProfile(dps.toArray(new DataProfile[0]), null); 1910 } 1911 } 1912 } 1913 onActionIntentProvisioningApnAlarm(Intent intent)1914 protected void onActionIntentProvisioningApnAlarm(Intent intent) { 1915 if (DBG) log("onActionIntentProvisioningApnAlarm: action=" + intent.getAction()); 1916 Message msg = obtainMessage(DctConstants.EVENT_PROVISIONING_APN_ALARM, 1917 intent.getAction()); 1918 msg.arg1 = intent.getIntExtra(PROVISIONING_APN_ALARM_TAG_EXTRA, 0); 1919 sendMessage(msg); 1920 } 1921 startProvisioningApnAlarm()1922 protected void startProvisioningApnAlarm() { 1923 int delayInMs = Settings.Global.getInt(mResolver, 1924 Settings.Global.PROVISIONING_APN_ALARM_DELAY_IN_MS, 1925 PROVISIONING_APN_ALARM_DELAY_IN_MS_DEFAULT); 1926 if (Build.IS_DEBUGGABLE) { 1927 // Allow debug code to use a system property to provide another value 1928 String delayInMsStrg = Integer.toString(delayInMs); 1929 delayInMsStrg = System.getProperty(DEBUG_PROV_APN_ALARM, delayInMsStrg); 1930 try { 1931 delayInMs = Integer.parseInt(delayInMsStrg); 1932 } catch (NumberFormatException e) { 1933 loge("startProvisioningApnAlarm: e=" + e); 1934 } 1935 } 1936 mProvisioningApnAlarmTag += 1; 1937 if (DBG) { 1938 log("startProvisioningApnAlarm: tag=" + mProvisioningApnAlarmTag + 1939 " delay=" + (delayInMs / 1000) + "s"); 1940 } 1941 Intent intent = new Intent(INTENT_PROVISIONING_APN_ALARM); 1942 intent.putExtra(PROVISIONING_APN_ALARM_TAG_EXTRA, mProvisioningApnAlarmTag); 1943 mProvisioningApnAlarmIntent = PendingIntent.getBroadcast(mPhone.getContext(), 0, intent, 1944 PendingIntent.FLAG_UPDATE_CURRENT); 1945 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 1946 SystemClock.elapsedRealtime() + delayInMs, mProvisioningApnAlarmIntent); 1947 } 1948 stopProvisioningApnAlarm()1949 protected void stopProvisioningApnAlarm() { 1950 if (DBG) { 1951 log("stopProvisioningApnAlarm: current tag=" + mProvisioningApnAlarmTag + 1952 " mProvsioningApnAlarmIntent=" + mProvisioningApnAlarmIntent); 1953 } 1954 mProvisioningApnAlarmTag += 1; 1955 if (mProvisioningApnAlarmIntent != null) { 1956 mAlarmManager.cancel(mProvisioningApnAlarmIntent); 1957 mProvisioningApnAlarmIntent = null; 1958 } 1959 } 1960 sendCleanUpConnection(boolean tearDown, ApnContext apnContext)1961 void sendCleanUpConnection(boolean tearDown, ApnContext apnContext) { 1962 if (DBG)log("sendCleanUpConnection: tearDown=" + tearDown + " apnContext=" + apnContext); 1963 Message msg = obtainMessage(DctConstants.EVENT_CLEAN_UP_CONNECTION); 1964 msg.arg1 = tearDown ? 1 : 0; 1965 msg.arg2 = 0; 1966 msg.obj = apnContext; 1967 sendMessage(msg); 1968 } 1969 sendRestartRadio()1970 void sendRestartRadio() { 1971 if (DBG)log("sendRestartRadio:"); 1972 Message msg = obtainMessage(DctConstants.EVENT_RESTART_RADIO); 1973 sendMessage(msg); 1974 } 1975 dump(FileDescriptor fd, PrintWriter pw, String[] args)1976 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1977 pw.println("DcTrackerBase:"); 1978 pw.println(" RADIO_TESTS=" + RADIO_TESTS); 1979 pw.println(" mInternalDataEnabled=" + mInternalDataEnabled); 1980 pw.println(" mUserDataEnabled=" + mUserDataEnabled); 1981 pw.println(" sPolicyDataEnabed=" + sPolicyDataEnabled); 1982 pw.println(" mDataEnabled:"); 1983 for(int i=0; i < mDataEnabled.length; i++) { 1984 pw.printf(" mDataEnabled[%d]=%b\n", i, mDataEnabled[i]); 1985 } 1986 pw.flush(); 1987 pw.println(" mEnabledCount=" + mEnabledCount); 1988 pw.println(" mRequestedApnType=" + mRequestedApnType); 1989 pw.println(" mPhone=" + mPhone.getPhoneName()); 1990 pw.println(" mActivity=" + mActivity); 1991 pw.println(" mState=" + mState); 1992 pw.println(" mTxPkts=" + mTxPkts); 1993 pw.println(" mRxPkts=" + mRxPkts); 1994 pw.println(" mNetStatPollPeriod=" + mNetStatPollPeriod); 1995 pw.println(" mNetStatPollEnabled=" + mNetStatPollEnabled); 1996 pw.println(" mDataStallTxRxSum=" + mDataStallTxRxSum); 1997 pw.println(" mDataStallAlarmTag=" + mDataStallAlarmTag); 1998 pw.println(" mDataStallDetectionEanbled=" + mDataStallDetectionEnabled); 1999 pw.println(" mSentSinceLastRecv=" + mSentSinceLastRecv); 2000 pw.println(" mNoRecvPollCount=" + mNoRecvPollCount); 2001 pw.println(" mResolver=" + mResolver); 2002 pw.println(" mIsWifiConnected=" + mIsWifiConnected); 2003 pw.println(" mReconnectIntent=" + mReconnectIntent); 2004 pw.println(" mCidActive=" + mCidActive); 2005 pw.println(" mAutoAttachOnCreation=" + mAutoAttachOnCreation); 2006 pw.println(" mIsScreenOn=" + mIsScreenOn); 2007 pw.println(" mUniqueIdGenerator=" + mUniqueIdGenerator); 2008 pw.flush(); 2009 pw.println(" ***************************************"); 2010 DcController dcc = mDcc; 2011 if (dcc != null) { 2012 dcc.dump(fd, pw, args); 2013 } else { 2014 pw.println(" mDcc=null"); 2015 } 2016 pw.println(" ***************************************"); 2017 HashMap<Integer, DataConnection> dcs = mDataConnections; 2018 if (dcs != null) { 2019 Set<Entry<Integer, DataConnection> > mDcSet = mDataConnections.entrySet(); 2020 pw.println(" mDataConnections: count=" + mDcSet.size()); 2021 for (Entry<Integer, DataConnection> entry : mDcSet) { 2022 pw.printf(" *** mDataConnection[%d] \n", entry.getKey()); 2023 entry.getValue().dump(fd, pw, args); 2024 } 2025 } else { 2026 pw.println("mDataConnections=null"); 2027 } 2028 pw.println(" ***************************************"); 2029 pw.flush(); 2030 HashMap<String, Integer> apnToDcId = mApnToDataConnectionId; 2031 if (apnToDcId != null) { 2032 Set<Entry<String, Integer>> apnToDcIdSet = apnToDcId.entrySet(); 2033 pw.println(" mApnToDataConnectonId size=" + apnToDcIdSet.size()); 2034 for (Entry<String, Integer> entry : apnToDcIdSet) { 2035 pw.printf(" mApnToDataConnectonId[%s]=%d\n", entry.getKey(), entry.getValue()); 2036 } 2037 } else { 2038 pw.println("mApnToDataConnectionId=null"); 2039 } 2040 pw.println(" ***************************************"); 2041 pw.flush(); 2042 ConcurrentHashMap<String, ApnContext> apnCtxs = mApnContexts; 2043 if (apnCtxs != null) { 2044 Set<Entry<String, ApnContext>> apnCtxsSet = apnCtxs.entrySet(); 2045 pw.println(" mApnContexts size=" + apnCtxsSet.size()); 2046 for (Entry<String, ApnContext> entry : apnCtxsSet) { 2047 entry.getValue().dump(fd, pw, args); 2048 } 2049 pw.println(" ***************************************"); 2050 } else { 2051 pw.println(" mApnContexts=null"); 2052 } 2053 pw.flush(); 2054 pw.println(" mActiveApn=" + mActiveApn); 2055 ArrayList<ApnSetting> apnSettings = mAllApnSettings; 2056 if (apnSettings != null) { 2057 pw.println(" mAllApnSettings size=" + apnSettings.size()); 2058 for (int i=0; i < apnSettings.size(); i++) { 2059 pw.printf(" mAllApnSettings[%d]: %s\n", i, apnSettings.get(i)); 2060 } 2061 pw.flush(); 2062 } else { 2063 pw.println(" mAllApnSettings=null"); 2064 } 2065 pw.println(" mPreferredApn=" + mPreferredApn); 2066 pw.println(" mIsPsRestricted=" + mIsPsRestricted); 2067 pw.println(" mIsDisposed=" + mIsDisposed); 2068 pw.println(" mIntentReceiver=" + mIntentReceiver); 2069 pw.println(" mDataRoamingSettingObserver=" + mDataRoamingSettingObserver); 2070 pw.flush(); 2071 } 2072 } 2073