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