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