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