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; 18 19 import android.app.PendingIntent; 20 import android.os.AsyncResult; 21 import android.os.Handler; 22 import android.os.Message; 23 import android.os.RemoteException; 24 import android.provider.Settings; 25 import android.provider.Settings.SettingNotFoundException; 26 import android.text.TextUtils; 27 import android.util.Log; 28 29 import java.util.ArrayList; 30 31 /** 32 * {@hide} 33 * 34 */ 35 public abstract class DataConnectionTracker extends Handler { 36 protected static final boolean DBG = false; 37 protected final String LOG_TAG = "DataConnectionTracker"; 38 39 /** 40 * IDLE: ready to start data connection setup, default state 41 * INITING: state of issued setupDefaultPDP() but not finish yet 42 * CONNECTING: state of issued startPppd() but not finish yet 43 * SCANNING: data connection fails with one apn but other apns are available 44 * ready to start data connection on other apns (before INITING) 45 * CONNECTED: IP connection is setup 46 * DISCONNECTING: Connection.disconnect() has been called, but PDP 47 * context is not yet deactivated 48 * FAILED: data connection fail for all apns settings 49 * 50 * getDataConnectionState() maps State to DataState 51 * FAILED or IDLE : DISCONNECTED 52 * INITING or CONNECTING or SCANNING: CONNECTING 53 * CONNECTED : CONNECTED or DISCONNECTING 54 */ 55 public enum State { 56 IDLE, 57 INITING, 58 CONNECTING, 59 SCANNING, 60 CONNECTED, 61 DISCONNECTING, 62 FAILED 63 } 64 65 public enum Activity { 66 NONE, 67 DATAIN, 68 DATAOUT, 69 DATAINANDOUT, 70 DORMANT 71 } 72 73 /***** Event Codes *****/ 74 protected static final int EVENT_DATA_SETUP_COMPLETE = 1; 75 protected static final int EVENT_RADIO_AVAILABLE = 3; 76 protected static final int EVENT_RECORDS_LOADED = 4; 77 protected static final int EVENT_TRY_SETUP_DATA = 5; 78 protected static final int EVENT_DATA_STATE_CHANGED = 6; 79 protected static final int EVENT_POLL_PDP = 7; 80 protected static final int EVENT_GET_PDP_LIST_COMPLETE = 11; 81 protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE = 12; 82 protected static final int EVENT_VOICE_CALL_STARTED = 14; 83 protected static final int EVENT_VOICE_CALL_ENDED = 15; 84 protected static final int EVENT_GPRS_DETACHED = 19; 85 protected static final int EVENT_LINK_STATE_CHANGED = 20; 86 protected static final int EVENT_ROAMING_ON = 21; 87 protected static final int EVENT_ROAMING_OFF = 22; 88 protected static final int EVENT_ENABLE_NEW_APN = 23; 89 protected static final int EVENT_RESTORE_DEFAULT_APN = 24; 90 protected static final int EVENT_DISCONNECT_DONE = 25; 91 protected static final int EVENT_GPRS_ATTACHED = 26; 92 protected static final int EVENT_START_NETSTAT_POLL = 27; 93 protected static final int EVENT_START_RECOVERY = 28; 94 protected static final int EVENT_APN_CHANGED = 29; 95 protected static final int EVENT_CDMA_DATA_DETACHED = 30; 96 protected static final int EVENT_NV_READY = 31; 97 protected static final int EVENT_PS_RESTRICT_ENABLED = 32; 98 protected static final int EVENT_PS_RESTRICT_DISABLED = 33; 99 public static final int EVENT_CLEAN_UP_CONNECTION = 34; 100 protected static final int EVENT_CDMA_OTA_PROVISION = 35; 101 protected static final int EVENT_RESTART_RADIO = 36; 102 protected static final int EVENT_SET_MASTER_DATA_ENABLE = 37; 103 protected static final int EVENT_RESET_DONE = 38; 104 105 /***** Constants *****/ 106 107 protected static final int APN_INVALID_ID = -1; 108 protected static final int APN_DEFAULT_ID = 0; 109 protected static final int APN_MMS_ID = 1; 110 protected static final int APN_SUPL_ID = 2; 111 protected static final int APN_DUN_ID = 3; 112 protected static final int APN_HIPRI_ID = 4; 113 protected static final int APN_NUM_TYPES = 5; 114 115 protected static final int DISABLED = 0; 116 protected static final int ENABLED = 1; 117 118 // responds to the setDataEnabled call - used independently from the APN requests 119 protected boolean mMasterDataEnabled = true; 120 121 protected boolean[] dataEnabled = new boolean[APN_NUM_TYPES]; 122 protected int enabledCount = 0; 123 124 /* Currently requested APN type */ 125 protected String mRequestedApnType = Phone.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 ping deadline, in seconds. */ 139 protected static final int DEFAULT_PING_DEADLINE = 5; 140 /** Default max failure count before attempting to network re-registration. */ 141 protected static final int DEFAULT_MAX_PDP_RESET_FAIL = 3; 142 143 /** 144 * After detecting a potential connection problem, this is the max number 145 * of subsequent polls before attempting a radio reset. At this point, 146 * poll interval is 5 seconds (POLL_NETSTAT_SLOW_MILLIS), so set this to 147 * poll for about 2 more minutes. 148 */ 149 protected static final int NO_RECV_POLL_LIMIT = 24; 150 151 // 1 sec. default polling interval when screen is on. 152 protected static final int POLL_NETSTAT_MILLIS = 1000; 153 // 10 min. default polling interval when screen is off. 154 protected static final int POLL_NETSTAT_SCREEN_OFF_MILLIS = 1000*60*10; 155 // 2 min for round trip time 156 protected static final int POLL_LONGEST_RTT = 120 * 1000; 157 // 10 for packets without ack 158 protected static final int NUMBER_SENT_PACKETS_OF_HANG = 10; 159 // how long to wait before switching back to default APN 160 protected static final int RESTORE_DEFAULT_APN_DELAY = 1 * 60 * 1000; 161 // system property that can override the above value 162 protected static final String APN_RESTORE_DELAY_PROP_NAME = "android.telephony.apn-restore"; 163 // represents an invalid IP address 164 protected static final String NULL_IP = "0.0.0.0"; 165 166 167 // member variables 168 protected PhoneBase phone; 169 protected Activity activity = Activity.NONE; 170 protected State state = State.IDLE; 171 protected Handler mDataConnectionTracker = null; 172 173 174 protected long txPkts, rxPkts, sentSinceLastRecv; 175 protected int netStatPollPeriod; 176 protected int mNoRecvPollCount = 0; 177 protected boolean netStatPollEnabled = false; 178 179 /** Manage the behavior of data retry after failure */ 180 protected RetryManager mRetryMgr = new RetryManager(); 181 182 // wifi connection status will be updated by sticky intent 183 protected boolean mIsWifiConnected = false; 184 185 /** Intent sent when the reconnect alarm fires. */ 186 protected PendingIntent mReconnectIntent = null; 187 188 /** CID of active data connection */ 189 protected int cidActive; 190 191 /** 192 * Default constructor 193 */ 194 protected DataConnectionTracker(PhoneBase phone) { 195 super(); 196 this.phone = phone; 197 } 198 199 public abstract void dispose(); 200 201 public Activity getActivity() { 202 return activity; 203 } 204 205 public State getState() { 206 return state; 207 } 208 209 public String getStateInString() { 210 switch (state) { 211 case IDLE: return "IDLE"; 212 case INITING: return "INIT"; 213 case CONNECTING: return "CING"; 214 case SCANNING: return "SCAN"; 215 case CONNECTED: return "CNTD"; 216 case DISCONNECTING: return "DING"; 217 case FAILED: return "FAIL"; 218 default: return "ERRO"; 219 } 220 } 221 222 /** 223 * The data connection is expected to be setup while device 224 * 1. has Icc card 225 * 2. registered for data service 226 * 3. user doesn't explicitly disable data service 227 * 4. wifi is not on 228 * 229 * @return false while no data connection if all above requirements are met. 230 */ 231 public abstract boolean isDataConnectionAsDesired(); 232 233 //The data roaming setting is now located in the shared preferences. 234 // See if the requested preference value is the same as that stored in 235 // the shared values. If it is not, then update it. 236 public void setDataOnRoamingEnabled(boolean enabled) { 237 if (getDataOnRoamingEnabled() != enabled) { 238 Settings.Secure.putInt(phone.getContext().getContentResolver(), 239 Settings.Secure.DATA_ROAMING, enabled ? 1 : 0); 240 if (phone.getServiceState().getRoaming()) { 241 if (enabled) { 242 mRetryMgr.resetRetryCount(); 243 } 244 sendMessage(obtainMessage(EVENT_ROAMING_ON)); 245 } 246 } 247 } 248 249 //Retrieve the data roaming setting from the shared preferences. 250 public boolean getDataOnRoamingEnabled() { 251 try { 252 return Settings.Secure.getInt(phone.getContext().getContentResolver(), 253 Settings.Secure.DATA_ROAMING) > 0; 254 } catch (SettingNotFoundException snfe) { 255 return false; 256 } 257 } 258 259 // abstract handler methods 260 protected abstract boolean onTrySetupData(String reason); 261 protected abstract void onRoamingOff(); 262 protected abstract void onRoamingOn(); 263 protected abstract void onRadioAvailable(); 264 protected abstract void onRadioOffOrNotAvailable(); 265 protected abstract void onDataSetupComplete(AsyncResult ar); 266 protected abstract void onDisconnectDone(AsyncResult ar); 267 protected abstract void onResetDone(AsyncResult ar); 268 protected abstract void onVoiceCallStarted(); 269 protected abstract void onVoiceCallEnded(); 270 protected abstract void onCleanUpConnection(boolean tearDown, String reason); 271 272 @Override 273 public void handleMessage (Message msg) { 274 switch (msg.what) { 275 276 case EVENT_ENABLE_NEW_APN: 277 onEnableApn(msg.arg1, msg.arg2); 278 break; 279 280 case EVENT_TRY_SETUP_DATA: 281 String reason = null; 282 if (msg.obj instanceof String) { 283 reason = (String)msg.obj; 284 } 285 onTrySetupData(reason); 286 break; 287 288 case EVENT_ROAMING_OFF: 289 if (getDataOnRoamingEnabled() == false) { 290 mRetryMgr.resetRetryCount(); 291 } 292 onRoamingOff(); 293 break; 294 295 case EVENT_ROAMING_ON: 296 onRoamingOn(); 297 break; 298 299 case EVENT_RADIO_AVAILABLE: 300 onRadioAvailable(); 301 break; 302 303 case EVENT_RADIO_OFF_OR_NOT_AVAILABLE: 304 onRadioOffOrNotAvailable(); 305 break; 306 307 case EVENT_DATA_SETUP_COMPLETE: 308 cidActive = msg.arg1; 309 onDataSetupComplete((AsyncResult) msg.obj); 310 break; 311 312 case EVENT_DISCONNECT_DONE: 313 onDisconnectDone((AsyncResult) msg.obj); 314 break; 315 316 case EVENT_VOICE_CALL_STARTED: 317 onVoiceCallStarted(); 318 break; 319 320 case EVENT_VOICE_CALL_ENDED: 321 onVoiceCallEnded(); 322 break; 323 324 case EVENT_CLEAN_UP_CONNECTION: 325 boolean tearDown = (msg.arg1 == 0) ? false : true; 326 onCleanUpConnection(tearDown, (String)msg.obj); 327 break; 328 329 case EVENT_SET_MASTER_DATA_ENABLE: 330 boolean enabled = (msg.arg1 == ENABLED) ? true : false; 331 onSetDataEnabled(enabled); 332 break; 333 334 case EVENT_RESET_DONE: 335 onResetDone((AsyncResult) msg.obj); 336 break; 337 338 default: 339 Log.e("DATA", "Unidentified event = " + msg.what); 340 break; 341 } 342 } 343 344 /** 345 * Report the current state of data connectivity (enabled or disabled) 346 * @return {@code false} if data connectivity has been explicitly disabled, 347 * {@code true} otherwise. 348 */ 349 public synchronized boolean getDataEnabled() { 350 return dataEnabled[APN_DEFAULT_ID]; 351 } 352 353 /** 354 * Report on whether data connectivity is enabled 355 * @return {@code false} if data connectivity has been explicitly disabled, 356 * {@code true} otherwise. 357 */ 358 public boolean getAnyDataEnabled() { 359 return (enabledCount != 0); 360 } 361 362 protected abstract void startNetStatPoll(); 363 364 protected abstract void stopNetStatPoll(); 365 366 protected abstract void restartRadio(); 367 368 protected abstract void log(String s); 369 370 protected int apnTypeToId(String type) { 371 if (TextUtils.equals(type, Phone.APN_TYPE_DEFAULT)) { 372 return APN_DEFAULT_ID; 373 } else if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) { 374 return APN_MMS_ID; 375 } else if (TextUtils.equals(type, Phone.APN_TYPE_SUPL)) { 376 return APN_SUPL_ID; 377 } else if (TextUtils.equals(type, Phone.APN_TYPE_DUN)) { 378 return APN_DUN_ID; 379 } else if (TextUtils.equals(type, Phone.APN_TYPE_HIPRI)) { 380 return APN_HIPRI_ID; 381 } else { 382 return APN_INVALID_ID; 383 } 384 } 385 386 protected String apnIdToType(int id) { 387 switch (id) { 388 case APN_DEFAULT_ID: 389 return Phone.APN_TYPE_DEFAULT; 390 case APN_MMS_ID: 391 return Phone.APN_TYPE_MMS; 392 case APN_SUPL_ID: 393 return Phone.APN_TYPE_SUPL; 394 case APN_DUN_ID: 395 return Phone.APN_TYPE_DUN; 396 case APN_HIPRI_ID: 397 return Phone.APN_TYPE_HIPRI; 398 default: 399 Log.e(LOG_TAG, "Unknown id (" + id + ") in apnIdToType"); 400 return Phone.APN_TYPE_DEFAULT; 401 } 402 } 403 404 protected abstract boolean isApnTypeActive(String type); 405 406 protected abstract boolean isApnTypeAvailable(String type); 407 408 protected abstract String[] getActiveApnTypes(); 409 410 protected abstract String getActiveApnString(); 411 412 public abstract ArrayList<DataConnection> getAllDataConnections(); 413 414 protected abstract String getInterfaceName(String apnType); 415 416 protected abstract String getIpAddress(String apnType); 417 418 protected abstract String getGateway(String apnType); 419 420 protected abstract String[] getDnsServers(String apnType); 421 422 protected abstract void setState(State s); 423 424 protected synchronized boolean isEnabled(int id) { 425 if (id != APN_INVALID_ID) { 426 return dataEnabled[id]; 427 } 428 return false; 429 } 430 431 /** 432 * Ensure that we are connected to an APN of the specified type. 433 * @param type the APN type (currently the only valid values 434 * are {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL}) 435 * @return the result of the operation. Success is indicated by 436 * a return value of either {@code Phone.APN_ALREADY_ACTIVE} or 437 * {@code Phone.APN_REQUEST_STARTED}. In the latter case, a broadcast 438 * will be sent by the ConnectivityManager when a connection to 439 * the APN has been established. 440 */ 441 public synchronized int enableApnType(String type) { 442 int id = apnTypeToId(type); 443 if (id == APN_INVALID_ID) { 444 return Phone.APN_REQUEST_FAILED; 445 } 446 447 if (DBG) Log.d(LOG_TAG, "enableApnType("+type+"), isApnTypeActive = " 448 + isApnTypeActive(type) + " and state = " + state); 449 450 if (!isApnTypeAvailable(type)) { 451 if (DBG) Log.d(LOG_TAG, "type not available"); 452 return Phone.APN_TYPE_NOT_AVAILABLE; 453 } 454 455 // just because it's active doesn't mean we had it explicitly requested before 456 // (a broad default may handle many types). make sure we mark it enabled 457 // so if the default is disabled we keep the connection for others 458 setEnabled(id, true); 459 460 if (isApnTypeActive(type)) { 461 if (state == State.INITING) return Phone.APN_REQUEST_STARTED; 462 else if (state == State.CONNECTED) return Phone.APN_ALREADY_ACTIVE; 463 } 464 return Phone.APN_REQUEST_STARTED; 465 } 466 467 /** 468 * The APN of the specified type is no longer needed. Ensure that if 469 * use of the default APN has not been explicitly disabled, we are connected 470 * to the default APN. 471 * @param type the APN type. The only valid values are currently 472 * {@link Phone#APN_TYPE_MMS} and {@link Phone#APN_TYPE_SUPL}. 473 * @return 474 */ 475 public synchronized int disableApnType(String type) { 476 if (DBG) Log.d(LOG_TAG, "disableApnType("+type+")"); 477 int id = apnTypeToId(type); 478 if (id == APN_INVALID_ID) { 479 return Phone.APN_REQUEST_FAILED; 480 } 481 if (isEnabled(id)) { 482 setEnabled(id, false); 483 if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) { 484 if (dataEnabled[APN_DEFAULT_ID]) { 485 return Phone.APN_ALREADY_ACTIVE; 486 } else { 487 return Phone.APN_REQUEST_STARTED; 488 } 489 } else { 490 return Phone.APN_REQUEST_STARTED; 491 } 492 } else { 493 return Phone.APN_REQUEST_FAILED; 494 } 495 } 496 497 private void setEnabled(int id, boolean enable) { 498 if (DBG) Log.d(LOG_TAG, "setEnabled(" + id + ", " + enable + ") with old state = " + 499 dataEnabled[id] + " and enabledCount = " + enabledCount); 500 501 Message msg = obtainMessage(EVENT_ENABLE_NEW_APN); 502 msg.arg1 = id; 503 msg.arg2 = (enable ? ENABLED : DISABLED); 504 sendMessage(msg); 505 } 506 507 protected synchronized void onEnableApn(int apnId, int enabled) { 508 if (DBG) { 509 Log.d(LOG_TAG, "EVENT_APN_ENABLE_REQUEST " + apnId + ", " + enabled); 510 Log.d(LOG_TAG, " dataEnabled = " + dataEnabled[apnId] + 511 ", enabledCount = " + enabledCount + 512 ", isApnTypeActive = " + isApnTypeActive(apnIdToType(apnId))); 513 } 514 if (enabled == ENABLED) { 515 if (!dataEnabled[apnId]) { 516 dataEnabled[apnId] = true; 517 enabledCount++; 518 } 519 String type = apnIdToType(apnId); 520 if (!isApnTypeActive(type)) { 521 mRequestedApnType = type; 522 onEnableNewApn(); 523 } 524 } else { 525 // disable 526 if (dataEnabled[apnId]) { 527 dataEnabled[apnId] = false; 528 enabledCount--; 529 if (enabledCount == 0) { 530 onCleanUpConnection(true, Phone.REASON_DATA_DISABLED); 531 } else if (dataEnabled[APN_DEFAULT_ID] == true && 532 !isApnTypeActive(Phone.APN_TYPE_DEFAULT)) { 533 mRequestedApnType = Phone.APN_TYPE_DEFAULT; 534 onEnableNewApn(); 535 } 536 } 537 } 538 } 539 540 /** 541 * Called when we switch APNs. 542 * 543 * mRequestedApnType is set prior to call 544 * To be overridden. 545 */ 546 protected void onEnableNewApn() { 547 } 548 549 /** 550 * Prevent mobile data connections from being established, 551 * or once again allow mobile data connections. If the state 552 * toggles, then either tear down or set up data, as 553 * appropriate to match the new state. 554 * <p>This operation only affects the default APN, and if the same APN is 555 * currently being used for MMS traffic, the teardown will not happen 556 * even when {@code enable} is {@code false}.</p> 557 * @param enable indicates whether to enable ({@code true}) or disable ({@code false}) data 558 * @return {@code true} if the operation succeeded 559 */ 560 public boolean setDataEnabled(boolean enable) { 561 if (DBG) Log.d(LOG_TAG, "setDataEnabled(" + enable + ")"); 562 563 Message msg = obtainMessage(EVENT_SET_MASTER_DATA_ENABLE); 564 msg.arg1 = (enable ? ENABLED : DISABLED); 565 sendMessage(msg); 566 return true; 567 } 568 569 protected void onSetDataEnabled(boolean enable) { 570 if (mMasterDataEnabled != enable) { 571 mMasterDataEnabled = enable; 572 if (enable) { 573 mRetryMgr.resetRetryCount(); 574 onTrySetupData(Phone.REASON_DATA_ENABLED); 575 } else { 576 onCleanUpConnection(true, Phone.REASON_DATA_DISABLED); 577 } 578 } 579 } 580 581 582 } 583