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