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