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