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