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 com.android.internal.telephony.CallTracker; 20import com.android.internal.telephony.CarrierSignalAgent; 21import com.android.internal.telephony.CommandException; 22import com.android.internal.telephony.DctConstants; 23import com.android.internal.telephony.Phone; 24import com.android.internal.telephony.PhoneConstants; 25import com.android.internal.telephony.RILConstants; 26import com.android.internal.telephony.RetryManager; 27import com.android.internal.telephony.ServiceStateTracker; 28import com.android.internal.util.AsyncChannel; 29import com.android.internal.util.Protocol; 30import com.android.internal.util.State; 31import com.android.internal.util.StateMachine; 32 33import android.app.PendingIntent; 34import android.content.Context; 35import android.net.ConnectivityManager; 36import android.net.LinkProperties; 37import android.net.NetworkAgent; 38import android.net.NetworkCapabilities; 39import android.net.NetworkInfo; 40import android.net.NetworkMisc; 41import android.net.ProxyInfo; 42import android.os.AsyncResult; 43import android.os.Looper; 44import android.os.Message; 45import android.os.SystemClock; 46import android.os.SystemProperties; 47import android.telephony.Rlog; 48import android.telephony.ServiceState; 49import android.telephony.TelephonyManager; 50import android.text.TextUtils; 51import android.util.Pair; 52import android.util.Patterns; 53import android.util.TimeUtils; 54 55import java.io.FileDescriptor; 56import java.io.PrintWriter; 57import java.io.StringWriter; 58import java.util.ArrayList; 59import java.util.Locale; 60import java.util.concurrent.atomic.AtomicInteger; 61import java.net.InetAddress; 62import java.util.Collection; 63import java.util.HashMap; 64 65/** 66 * {@hide} 67 * 68 * DataConnection StateMachine. 69 * 70 * This a class for representing a single data connection, with instances of this 71 * class representing a connection via the cellular network. There may be multiple 72 * data connections and all of them are managed by the <code>DataConnectionTracker</code>. 73 * 74 * NOTE: All DataConnection objects must be running on the same looper, which is the default 75 * as the coordinator has members which are used without synchronization. 76 */ 77public class DataConnection extends StateMachine { 78 private static final boolean DBG = true; 79 private static final boolean VDBG = true; 80 81 private static final String NETWORK_TYPE = "MOBILE"; 82 83 // The data connection controller 84 private DcController mDcController; 85 86 // The Tester for failing all bringup's 87 private DcTesterFailBringUpAll mDcTesterFailBringUpAll; 88 89 private static AtomicInteger mInstanceNumber = new AtomicInteger(0); 90 private AsyncChannel mAc; 91 92 // The DCT that's talking to us, we only support one! 93 private DcTracker mDct = null; 94 95 protected String[] mPcscfAddr; 96 97 /** 98 * Used internally for saving connecting parameters. 99 */ 100 public static class ConnectionParams { 101 int mTag; 102 ApnContext mApnContext; 103 int mProfileId; 104 int mRilRat; 105 Message mOnCompletedMsg; 106 final int mConnectionGeneration; 107 108 ConnectionParams(ApnContext apnContext, int profileId, 109 int rilRadioTechnology, Message onCompletedMsg, int connectionGeneration) { 110 mApnContext = apnContext; 111 mProfileId = profileId; 112 mRilRat = rilRadioTechnology; 113 mOnCompletedMsg = onCompletedMsg; 114 mConnectionGeneration = connectionGeneration; 115 } 116 117 @Override 118 public String toString() { 119 return "{mTag=" + mTag + " mApnContext=" + mApnContext 120 + " mProfileId=" + mProfileId 121 + " mRat=" + mRilRat 122 + " mOnCompletedMsg=" + msgToString(mOnCompletedMsg) + "}"; 123 } 124 } 125 126 /** 127 * Used internally for saving disconnecting parameters. 128 */ 129 public static class DisconnectParams { 130 int mTag; 131 public ApnContext mApnContext; 132 String mReason; 133 Message mOnCompletedMsg; 134 135 DisconnectParams(ApnContext apnContext, String reason, Message onCompletedMsg) { 136 mApnContext = apnContext; 137 mReason = reason; 138 mOnCompletedMsg = onCompletedMsg; 139 } 140 141 @Override 142 public String toString() { 143 return "{mTag=" + mTag + " mApnContext=" + mApnContext 144 + " mReason=" + mReason 145 + " mOnCompletedMsg=" + msgToString(mOnCompletedMsg) + "}"; 146 } 147 } 148 149 private ApnSetting mApnSetting; 150 private ConnectionParams mConnectionParams; 151 private DisconnectParams mDisconnectParams; 152 private DcFailCause mDcFailCause; 153 154 private Phone mPhone; 155 private LinkProperties mLinkProperties = new LinkProperties(); 156 private long mCreateTime; 157 private long mLastFailTime; 158 private DcFailCause mLastFailCause; 159 private static final String NULL_IP = "0.0.0.0"; 160 private Object mUserData; 161 private int mRilRat = Integer.MAX_VALUE; 162 private int mDataRegState = Integer.MAX_VALUE; 163 private NetworkInfo mNetworkInfo; 164 private NetworkAgent mNetworkAgent; 165 166 int mTag; 167 public int mCid; 168 public HashMap<ApnContext, ConnectionParams> mApnContexts = null; 169 PendingIntent mReconnectIntent = null; 170 171 172 // ***** Event codes for driving the state machine, package visible for Dcc 173 static final int BASE = Protocol.BASE_DATA_CONNECTION; 174 static final int EVENT_CONNECT = BASE + 0; 175 static final int EVENT_SETUP_DATA_CONNECTION_DONE = BASE + 1; 176 static final int EVENT_GET_LAST_FAIL_DONE = BASE + 2; 177 static final int EVENT_DEACTIVATE_DONE = BASE + 3; 178 static final int EVENT_DISCONNECT = BASE + 4; 179 static final int EVENT_RIL_CONNECTED = BASE + 5; 180 static final int EVENT_DISCONNECT_ALL = BASE + 6; 181 static final int EVENT_DATA_STATE_CHANGED = BASE + 7; 182 static final int EVENT_TEAR_DOWN_NOW = BASE + 8; 183 static final int EVENT_LOST_CONNECTION = BASE + 9; 184 static final int EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED = BASE + 11; 185 static final int EVENT_DATA_CONNECTION_ROAM_ON = BASE + 12; 186 static final int EVENT_DATA_CONNECTION_ROAM_OFF = BASE + 13; 187 static final int EVENT_BW_REFRESH_RESPONSE = BASE + 14; 188 static final int EVENT_DATA_CONNECTION_VOICE_CALL_STARTED = BASE + 15; 189 static final int EVENT_DATA_CONNECTION_VOICE_CALL_ENDED = BASE + 16; 190 191 private static final int CMD_TO_STRING_COUNT = 192 EVENT_DATA_CONNECTION_VOICE_CALL_ENDED - BASE + 1; 193 194 private static String[] sCmdToString = new String[CMD_TO_STRING_COUNT]; 195 static { 196 sCmdToString[EVENT_CONNECT - BASE] = "EVENT_CONNECT"; 197 sCmdToString[EVENT_SETUP_DATA_CONNECTION_DONE - BASE] = 198 "EVENT_SETUP_DATA_CONNECTION_DONE"; 199 sCmdToString[EVENT_GET_LAST_FAIL_DONE - BASE] = "EVENT_GET_LAST_FAIL_DONE"; 200 sCmdToString[EVENT_DEACTIVATE_DONE - BASE] = "EVENT_DEACTIVATE_DONE"; 201 sCmdToString[EVENT_DISCONNECT - BASE] = "EVENT_DISCONNECT"; 202 sCmdToString[EVENT_RIL_CONNECTED - BASE] = "EVENT_RIL_CONNECTED"; 203 sCmdToString[EVENT_DISCONNECT_ALL - BASE] = "EVENT_DISCONNECT_ALL"; 204 sCmdToString[EVENT_DATA_STATE_CHANGED - BASE] = "EVENT_DATA_STATE_CHANGED"; 205 sCmdToString[EVENT_TEAR_DOWN_NOW - BASE] = "EVENT_TEAR_DOWN_NOW"; 206 sCmdToString[EVENT_LOST_CONNECTION - BASE] = "EVENT_LOST_CONNECTION"; 207 sCmdToString[EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED - BASE] = 208 "EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED"; 209 sCmdToString[EVENT_DATA_CONNECTION_ROAM_ON - BASE] = "EVENT_DATA_CONNECTION_ROAM_ON"; 210 sCmdToString[EVENT_DATA_CONNECTION_ROAM_OFF - BASE] = "EVENT_DATA_CONNECTION_ROAM_OFF"; 211 sCmdToString[EVENT_BW_REFRESH_RESPONSE - BASE] = "EVENT_BW_REFRESH_RESPONSE"; 212 sCmdToString[EVENT_DATA_CONNECTION_VOICE_CALL_STARTED - BASE] = 213 "EVENT_DATA_CONNECTION_VOICE_CALL_STARTED"; 214 sCmdToString[EVENT_DATA_CONNECTION_VOICE_CALL_ENDED - BASE] = 215 "EVENT_DATA_CONNECTION_VOICE_CALL_ENDED"; 216 } 217 // Convert cmd to string or null if unknown 218 static String cmdToString(int cmd) { 219 String value; 220 cmd -= BASE; 221 if ((cmd >= 0) && (cmd < sCmdToString.length)) { 222 value = sCmdToString[cmd]; 223 } else { 224 value = DcAsyncChannel.cmdToString(cmd + BASE); 225 } 226 if (value == null) { 227 value = "0x" + Integer.toHexString(cmd + BASE); 228 } 229 return value; 230 } 231 232 /** 233 * Create the connection object 234 * 235 * @param phone the Phone 236 * @param id the connection id 237 * @return DataConnection that was created. 238 */ 239 public static DataConnection makeDataConnection(Phone phone, int id, 240 DcTracker dct, DcTesterFailBringUpAll failBringUpAll, 241 DcController dcc) { 242 DataConnection dc = new DataConnection(phone, 243 "DC-" + mInstanceNumber.incrementAndGet(), id, dct, failBringUpAll, dcc); 244 dc.start(); 245 if (DBG) dc.log("Made " + dc.getName()); 246 return dc; 247 } 248 249 void dispose() { 250 log("dispose: call quiteNow()"); 251 quitNow(); 252 } 253 254 /* Getter functions */ 255 256 NetworkCapabilities getCopyNetworkCapabilities() { 257 return makeNetworkCapabilities(); 258 } 259 260 LinkProperties getCopyLinkProperties() { 261 return new LinkProperties(mLinkProperties); 262 } 263 264 boolean getIsInactive() { 265 return getCurrentState() == mInactiveState; 266 } 267 268 int getCid() { 269 return mCid; 270 } 271 272 ApnSetting getApnSetting() { 273 return mApnSetting; 274 } 275 276 void setLinkPropertiesHttpProxy(ProxyInfo proxy) { 277 mLinkProperties.setHttpProxy(proxy); 278 } 279 280 public static class UpdateLinkPropertyResult { 281 public DataCallResponse.SetupResult setupResult = DataCallResponse.SetupResult.SUCCESS; 282 public LinkProperties oldLp; 283 public LinkProperties newLp; 284 public UpdateLinkPropertyResult(LinkProperties curLp) { 285 oldLp = curLp; 286 newLp = curLp; 287 } 288 } 289 290 public boolean isIpv4Connected() { 291 boolean ret = false; 292 Collection <InetAddress> addresses = mLinkProperties.getAddresses(); 293 294 for (InetAddress addr: addresses) { 295 if (addr instanceof java.net.Inet4Address) { 296 java.net.Inet4Address i4addr = (java.net.Inet4Address) addr; 297 if (!i4addr.isAnyLocalAddress() && !i4addr.isLinkLocalAddress() && 298 !i4addr.isLoopbackAddress() && !i4addr.isMulticastAddress()) { 299 ret = true; 300 break; 301 } 302 } 303 } 304 return ret; 305 } 306 307 public boolean isIpv6Connected() { 308 boolean ret = false; 309 Collection <InetAddress> addresses = mLinkProperties.getAddresses(); 310 311 for (InetAddress addr: addresses) { 312 if (addr instanceof java.net.Inet6Address) { 313 java.net.Inet6Address i6addr = (java.net.Inet6Address) addr; 314 if (!i6addr.isAnyLocalAddress() && !i6addr.isLinkLocalAddress() && 315 !i6addr.isLoopbackAddress() && !i6addr.isMulticastAddress()) { 316 ret = true; 317 break; 318 } 319 } 320 } 321 return ret; 322 } 323 324 public UpdateLinkPropertyResult updateLinkProperty(DataCallResponse newState) { 325 UpdateLinkPropertyResult result = new UpdateLinkPropertyResult(mLinkProperties); 326 327 if (newState == null) return result; 328 329 DataCallResponse.SetupResult setupResult; 330 result.newLp = new LinkProperties(); 331 332 // set link properties based on data call response 333 result.setupResult = setLinkProperties(newState, result.newLp); 334 if (result.setupResult != DataCallResponse.SetupResult.SUCCESS) { 335 if (DBG) log("updateLinkProperty failed : " + result.setupResult); 336 return result; 337 } 338 // copy HTTP proxy as it is not part DataCallResponse. 339 result.newLp.setHttpProxy(mLinkProperties.getHttpProxy()); 340 341 checkSetMtu(mApnSetting, result.newLp); 342 343 mLinkProperties = result.newLp; 344 345 updateTcpBufferSizes(mRilRat); 346 347 if (DBG && (! result.oldLp.equals(result.newLp))) { 348 log("updateLinkProperty old LP=" + result.oldLp); 349 log("updateLinkProperty new LP=" + result.newLp); 350 } 351 352 if (result.newLp.equals(result.oldLp) == false && 353 mNetworkAgent != null) { 354 mNetworkAgent.sendLinkProperties(mLinkProperties); 355 } 356 357 return result; 358 } 359 360 /** 361 * Read the MTU value from link properties where it can be set from network. In case 362 * not set by the network, set it again using the mtu szie value defined in the APN 363 * database for the connected APN 364 */ 365 private void checkSetMtu(ApnSetting apn, LinkProperties lp) { 366 if (lp == null) return; 367 368 if (apn == null || lp == null) return; 369 370 if (lp.getMtu() != PhoneConstants.UNSET_MTU) { 371 if (DBG) log("MTU set by call response to: " + lp.getMtu()); 372 return; 373 } 374 375 if (apn != null && apn.mtu != PhoneConstants.UNSET_MTU) { 376 lp.setMtu(apn.mtu); 377 if (DBG) log("MTU set by APN to: " + apn.mtu); 378 return; 379 } 380 381 int mtu = mPhone.getContext().getResources().getInteger( 382 com.android.internal.R.integer.config_mobile_mtu); 383 if (mtu != PhoneConstants.UNSET_MTU) { 384 lp.setMtu(mtu); 385 if (DBG) log("MTU set by config resource to: " + mtu); 386 } 387 } 388 389 //***** Constructor (NOTE: uses dcc.getHandler() as its Handler) 390 private DataConnection(Phone phone, String name, int id, 391 DcTracker dct, DcTesterFailBringUpAll failBringUpAll, 392 DcController dcc) { 393 super(name, dcc.getHandler()); 394 setLogRecSize(300); 395 setLogOnlyTransitions(true); 396 if (DBG) log("DataConnection created"); 397 398 mPhone = phone; 399 mDct = dct; 400 mDcTesterFailBringUpAll = failBringUpAll; 401 mDcController = dcc; 402 mId = id; 403 mCid = -1; 404 ServiceState ss = mPhone.getServiceState(); 405 mRilRat = ss.getRilDataRadioTechnology(); 406 mDataRegState = mPhone.getServiceState().getDataRegState(); 407 int networkType = ss.getDataNetworkType(); 408 mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_MOBILE, 409 networkType, NETWORK_TYPE, TelephonyManager.getNetworkTypeName(networkType)); 410 mNetworkInfo.setRoaming(ss.getDataRoaming()); 411 mNetworkInfo.setIsAvailable(true); 412 // The network should be by default metered until we find it has NET_CAPABILITY_NOT_METERED 413 // capability. 414 mNetworkInfo.setMetered(true); 415 416 addState(mDefaultState); 417 addState(mInactiveState, mDefaultState); 418 addState(mActivatingState, mDefaultState); 419 addState(mActiveState, mDefaultState); 420 addState(mDisconnectingState, mDefaultState); 421 addState(mDisconnectingErrorCreatingConnection, mDefaultState); 422 setInitialState(mInactiveState); 423 424 mApnContexts = new HashMap<ApnContext, ConnectionParams>(); 425 } 426 427 /** 428 * Begin setting up a data connection, calls setupDataCall 429 * and the ConnectionParams will be returned with the 430 * EVENT_SETUP_DATA_CONNECTION_DONE AsyncResul.userObj. 431 * 432 * @param cp is the connection parameters 433 */ 434 private void onConnect(ConnectionParams cp) { 435 if (DBG) log("onConnect: carrier='" + mApnSetting.carrier 436 + "' APN='" + mApnSetting.apn 437 + "' proxy='" + mApnSetting.proxy + "' port='" + mApnSetting.port + "'"); 438 if (cp.mApnContext != null) cp.mApnContext.requestLog("DataConnection.onConnect"); 439 440 // Check if we should fake an error. 441 if (mDcTesterFailBringUpAll.getDcFailBringUp().mCounter > 0) { 442 DataCallResponse response = new DataCallResponse(); 443 response.version = mPhone.mCi.getRilVersion(); 444 response.status = mDcTesterFailBringUpAll.getDcFailBringUp().mFailCause.getErrorCode(); 445 response.cid = 0; 446 response.active = 0; 447 response.type = ""; 448 response.ifname = ""; 449 response.addresses = new String[0]; 450 response.dnses = new String[0]; 451 response.gateways = new String[0]; 452 response.suggestedRetryTime = 453 mDcTesterFailBringUpAll.getDcFailBringUp().mSuggestedRetryTime; 454 response.pcscf = new String[0]; 455 response.mtu = PhoneConstants.UNSET_MTU; 456 457 Message msg = obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE, cp); 458 AsyncResult.forMessage(msg, response, null); 459 sendMessage(msg); 460 if (DBG) { 461 log("onConnect: FailBringUpAll=" + mDcTesterFailBringUpAll.getDcFailBringUp() 462 + " send error response=" + response); 463 } 464 mDcTesterFailBringUpAll.getDcFailBringUp().mCounter -= 1; 465 return; 466 } 467 468 mCreateTime = -1; 469 mLastFailTime = -1; 470 mLastFailCause = DcFailCause.NONE; 471 472 // msg.obj will be returned in AsyncResult.userObj; 473 Message msg = obtainMessage(EVENT_SETUP_DATA_CONNECTION_DONE, cp); 474 msg.obj = cp; 475 476 int authType = mApnSetting.authType; 477 if (authType == -1) { 478 authType = TextUtils.isEmpty(mApnSetting.user) ? RILConstants.SETUP_DATA_AUTH_NONE 479 : RILConstants.SETUP_DATA_AUTH_PAP_CHAP; 480 } 481 482 String protocol; 483 if (mPhone.getServiceState().getDataRoamingFromRegistration()) { 484 protocol = mApnSetting.roamingProtocol; 485 } else { 486 protocol = mApnSetting.protocol; 487 } 488 489 mPhone.mCi.setupDataCall( 490 cp.mRilRat, 491 cp.mProfileId, 492 mApnSetting.apn, mApnSetting.user, mApnSetting.password, 493 authType, 494 protocol, msg); 495 } 496 497 /** 498 * TearDown the data connection when the deactivation is complete a Message with 499 * msg.what == EVENT_DEACTIVATE_DONE and msg.obj == AsyncResult with AsyncResult.obj 500 * containing the parameter o. 501 * 502 * @param o is the object returned in the AsyncResult.obj. 503 */ 504 private void tearDownData(Object o) { 505 int discReason = RILConstants.DEACTIVATE_REASON_NONE; 506 ApnContext apnContext = null; 507 if ((o != null) && (o instanceof DisconnectParams)) { 508 DisconnectParams dp = (DisconnectParams)o; 509 apnContext = dp.mApnContext; 510 if (TextUtils.equals(dp.mReason, Phone.REASON_RADIO_TURNED_OFF)) { 511 discReason = RILConstants.DEACTIVATE_REASON_RADIO_OFF; 512 } else if (TextUtils.equals(dp.mReason, Phone.REASON_PDP_RESET)) { 513 discReason = RILConstants.DEACTIVATE_REASON_PDP_RESET; 514 } 515 } 516 if (mPhone.mCi.getRadioState().isOn() 517 || (mPhone.getServiceState().getRilDataRadioTechnology() 518 == ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN )) { 519 String str = "tearDownData radio is on, call deactivateDataCall"; 520 if (DBG) log(str); 521 if (apnContext != null) apnContext.requestLog(str); 522 mPhone.mCi.deactivateDataCall(mCid, discReason, 523 obtainMessage(EVENT_DEACTIVATE_DONE, mTag, 0, o)); 524 } else { 525 String str = "tearDownData radio is off sendMessage EVENT_DEACTIVATE_DONE immediately"; 526 if (DBG) log(str); 527 if (apnContext != null) apnContext.requestLog(str); 528 AsyncResult ar = new AsyncResult(o, null, null); 529 sendMessage(obtainMessage(EVENT_DEACTIVATE_DONE, mTag, 0, ar)); 530 } 531 } 532 533 private void notifyAllWithEvent(ApnContext alreadySent, int event, String reason) { 534 mNetworkInfo.setDetailedState(mNetworkInfo.getDetailedState(), reason, 535 mNetworkInfo.getExtraInfo()); 536 for (ConnectionParams cp : mApnContexts.values()) { 537 ApnContext apnContext = cp.mApnContext; 538 if (apnContext == alreadySent) continue; 539 if (reason != null) apnContext.setReason(reason); 540 Pair<ApnContext, Integer> pair = 541 new Pair<ApnContext, Integer>(apnContext, cp.mConnectionGeneration); 542 Message msg = mDct.obtainMessage(event, pair); 543 AsyncResult.forMessage(msg); 544 msg.sendToTarget(); 545 } 546 } 547 548 private void notifyAllOfConnected(String reason) { 549 notifyAllWithEvent(null, DctConstants.EVENT_DATA_SETUP_COMPLETE, reason); 550 } 551 552 private void notifyAllOfDisconnectDcRetrying(String reason) { 553 notifyAllWithEvent(null, DctConstants.EVENT_DISCONNECT_DC_RETRYING, reason); 554 } 555 private void notifyAllDisconnectCompleted(DcFailCause cause) { 556 notifyAllWithEvent(null, DctConstants.EVENT_DISCONNECT_DONE, cause.toString()); 557 } 558 559 560 /** 561 * Send the connectionCompletedMsg. 562 * 563 * @param cp is the ConnectionParams 564 * @param cause and if no error the cause is DcFailCause.NONE 565 * @param sendAll is true if all contexts are to be notified 566 */ 567 private void notifyConnectCompleted(ConnectionParams cp, DcFailCause cause, boolean sendAll) { 568 ApnContext alreadySent = null; 569 570 if (cp != null && cp.mOnCompletedMsg != null) { 571 // Get the completed message but only use it once 572 Message connectionCompletedMsg = cp.mOnCompletedMsg; 573 cp.mOnCompletedMsg = null; 574 alreadySent = cp.mApnContext; 575 576 long timeStamp = System.currentTimeMillis(); 577 connectionCompletedMsg.arg1 = mCid; 578 579 if (cause == DcFailCause.NONE) { 580 mCreateTime = timeStamp; 581 AsyncResult.forMessage(connectionCompletedMsg); 582 } else { 583 mLastFailCause = cause; 584 mLastFailTime = timeStamp; 585 586 // Return message with a Throwable exception to signify an error. 587 if (cause == null) cause = DcFailCause.UNKNOWN; 588 AsyncResult.forMessage(connectionCompletedMsg, cause, 589 new Throwable(cause.toString())); 590 } 591 if (DBG) { 592 log("notifyConnectCompleted at " + timeStamp + " cause=" + cause 593 + " connectionCompletedMsg=" + msgToString(connectionCompletedMsg)); 594 } 595 596 connectionCompletedMsg.sendToTarget(); 597 } 598 if (sendAll) { 599 log("Send to all. " + alreadySent + " " + cause.toString()); 600 notifyAllWithEvent(alreadySent, DctConstants.EVENT_DATA_SETUP_COMPLETE_ERROR, 601 cause.toString()); 602 } 603 } 604 605 /** 606 * Send ar.userObj if its a message, which is should be back to originator. 607 * 608 * @param dp is the DisconnectParams. 609 */ 610 private void notifyDisconnectCompleted(DisconnectParams dp, boolean sendAll) { 611 if (VDBG) log("NotifyDisconnectCompleted"); 612 613 ApnContext alreadySent = null; 614 String reason = null; 615 616 if (dp != null && dp.mOnCompletedMsg != null) { 617 // Get the completed message but only use it once 618 Message msg = dp.mOnCompletedMsg; 619 dp.mOnCompletedMsg = null; 620 if (msg.obj instanceof ApnContext) { 621 alreadySent = (ApnContext)msg.obj; 622 } 623 reason = dp.mReason; 624 if (VDBG) { 625 log(String.format("msg=%s msg.obj=%s", msg.toString(), 626 ((msg.obj instanceof String) ? (String) msg.obj : "<no-reason>"))); 627 } 628 AsyncResult.forMessage(msg); 629 msg.sendToTarget(); 630 } 631 if (sendAll) { 632 if (reason == null) { 633 reason = DcFailCause.UNKNOWN.toString(); 634 } 635 notifyAllWithEvent(alreadySent, DctConstants.EVENT_DISCONNECT_DONE, reason); 636 } 637 if (DBG) log("NotifyDisconnectCompleted DisconnectParams=" + dp); 638 } 639 640 /* 641 * ************************************************************************** 642 * Begin Members and methods owned by DataConnectionTracker but stored 643 * in a DataConnection because there is one per connection. 644 * ************************************************************************** 645 */ 646 647 /* 648 * The id is owned by DataConnectionTracker. 649 */ 650 private int mId; 651 652 /** 653 * Get the DataConnection ID 654 */ 655 public int getDataConnectionId() { 656 return mId; 657 } 658 659 /* 660 * ************************************************************************** 661 * End members owned by DataConnectionTracker 662 * ************************************************************************** 663 */ 664 665 /** 666 * Clear all settings called when entering mInactiveState. 667 */ 668 private void clearSettings() { 669 if (DBG) log("clearSettings"); 670 671 mCreateTime = -1; 672 mLastFailTime = -1; 673 mLastFailCause = DcFailCause.NONE; 674 mCid = -1; 675 676 mPcscfAddr = new String[5]; 677 678 mLinkProperties = new LinkProperties(); 679 mApnContexts.clear(); 680 mApnSetting = null; 681 mDcFailCause = null; 682 } 683 684 /** 685 * Process setup completion. 686 * 687 * @param ar is the result 688 * @return SetupResult. 689 */ 690 private DataCallResponse.SetupResult onSetupConnectionCompleted(AsyncResult ar) { 691 DataCallResponse response = (DataCallResponse) ar.result; 692 ConnectionParams cp = (ConnectionParams) ar.userObj; 693 DataCallResponse.SetupResult result; 694 695 if (cp.mTag != mTag) { 696 if (DBG) { 697 log("onSetupConnectionCompleted stale cp.tag=" + cp.mTag + ", mtag=" + mTag); 698 } 699 result = DataCallResponse.SetupResult.ERR_Stale; 700 } else if (ar.exception != null) { 701 if (DBG) { 702 log("onSetupConnectionCompleted failed, ar.exception=" + ar.exception + 703 " response=" + response); 704 } 705 706 if (ar.exception instanceof CommandException 707 && ((CommandException) (ar.exception)).getCommandError() 708 == CommandException.Error.RADIO_NOT_AVAILABLE) { 709 result = DataCallResponse.SetupResult.ERR_BadCommand; 710 result.mFailCause = DcFailCause.RADIO_NOT_AVAILABLE; 711 } else if ((response == null) || (response.version < 4)) { 712 result = DataCallResponse.SetupResult.ERR_GetLastErrorFromRil; 713 } else { 714 result = DataCallResponse.SetupResult.ERR_RilError; 715 result.mFailCause = DcFailCause.fromInt(response.status); 716 } 717 } else if (response.status != 0) { 718 result = DataCallResponse.SetupResult.ERR_RilError; 719 result.mFailCause = DcFailCause.fromInt(response.status); 720 } else { 721 if (DBG) log("onSetupConnectionCompleted received successful DataCallResponse"); 722 mCid = response.cid; 723 724 mPcscfAddr = response.pcscf; 725 726 result = updateLinkProperty(response).setupResult; 727 } 728 729 return result; 730 } 731 732 private boolean isDnsOk(String[] domainNameServers) { 733 if (NULL_IP.equals(domainNameServers[0]) && NULL_IP.equals(domainNameServers[1]) 734 && !mPhone.isDnsCheckDisabled()) { 735 // Work around a race condition where QMI does not fill in DNS: 736 // Deactivate PDP and let DataConnectionTracker retry. 737 // Do not apply the race condition workaround for MMS APN 738 // if Proxy is an IP-address. 739 // Otherwise, the default APN will not be restored anymore. 740 if (!mApnSetting.types[0].equals(PhoneConstants.APN_TYPE_MMS) 741 || !isIpAddress(mApnSetting.mmsProxy)) { 742 log(String.format( 743 "isDnsOk: return false apn.types[0]=%s APN_TYPE_MMS=%s isIpAddress(%s)=%s", 744 mApnSetting.types[0], PhoneConstants.APN_TYPE_MMS, mApnSetting.mmsProxy, 745 isIpAddress(mApnSetting.mmsProxy))); 746 return false; 747 } 748 } 749 return true; 750 } 751 752 private static final String TCP_BUFFER_SIZES_GPRS = "4092,8760,48000,4096,8760,48000"; 753 private static final String TCP_BUFFER_SIZES_EDGE = "4093,26280,70800,4096,16384,70800"; 754 private static final String TCP_BUFFER_SIZES_UMTS = "58254,349525,1048576,58254,349525,1048576"; 755 private static final String TCP_BUFFER_SIZES_1XRTT= "16384,32768,131072,4096,16384,102400"; 756 private static final String TCP_BUFFER_SIZES_EVDO = "4094,87380,262144,4096,16384,262144"; 757 private static final String TCP_BUFFER_SIZES_EHRPD= "131072,262144,1048576,4096,16384,524288"; 758 private static final String TCP_BUFFER_SIZES_HSDPA= "61167,367002,1101005,8738,52429,262114"; 759 private static final String TCP_BUFFER_SIZES_HSPA = "40778,244668,734003,16777,100663,301990"; 760 private static final String TCP_BUFFER_SIZES_LTE = 761 "524288,1048576,2097152,262144,524288,1048576"; 762 private static final String TCP_BUFFER_SIZES_HSPAP= "122334,734003,2202010,32040,192239,576717"; 763 764 private void updateTcpBufferSizes(int rilRat) { 765 String sizes = null; 766 if (rilRat == ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA) { 767 // for now treat CA as LTE. Plan to surface the extra bandwith in a more 768 // precise manner which should affect buffer sizes 769 rilRat = ServiceState.RIL_RADIO_TECHNOLOGY_LTE; 770 } 771 String ratName = ServiceState.rilRadioTechnologyToString(rilRat).toLowerCase(Locale.ROOT); 772 // ServiceState gives slightly different names for EVDO tech ("evdo-rev.0" for ex) 773 // - patch it up: 774 if (rilRat == ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0 || 775 rilRat == ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A || 776 rilRat == ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_B) { 777 ratName = "evdo"; 778 } 779 780 // in the form: "ratname:rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max" 781 String[] configOverride = mPhone.getContext().getResources().getStringArray( 782 com.android.internal.R.array.config_mobile_tcp_buffers); 783 for (int i = 0; i < configOverride.length; i++) { 784 String[] split = configOverride[i].split(":"); 785 if (ratName.equals(split[0]) && split.length == 2) { 786 sizes = split[1]; 787 break; 788 } 789 } 790 791 if (sizes == null) { 792 // no override - use telephony defaults 793 // doing it this way allows device or carrier to just override the types they 794 // care about and inherit the defaults for the others. 795 switch (rilRat) { 796 case ServiceState.RIL_RADIO_TECHNOLOGY_GPRS: 797 sizes = TCP_BUFFER_SIZES_GPRS; 798 break; 799 case ServiceState.RIL_RADIO_TECHNOLOGY_EDGE: 800 sizes = TCP_BUFFER_SIZES_EDGE; 801 break; 802 case ServiceState.RIL_RADIO_TECHNOLOGY_UMTS: 803 sizes = TCP_BUFFER_SIZES_UMTS; 804 break; 805 case ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT: 806 sizes = TCP_BUFFER_SIZES_1XRTT; 807 break; 808 case ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0: 809 case ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A: 810 case ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_B: 811 sizes = TCP_BUFFER_SIZES_EVDO; 812 break; 813 case ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD: 814 sizes = TCP_BUFFER_SIZES_EHRPD; 815 break; 816 case ServiceState.RIL_RADIO_TECHNOLOGY_HSDPA: 817 sizes = TCP_BUFFER_SIZES_HSDPA; 818 break; 819 case ServiceState.RIL_RADIO_TECHNOLOGY_HSPA: 820 case ServiceState.RIL_RADIO_TECHNOLOGY_HSUPA: 821 sizes = TCP_BUFFER_SIZES_HSPA; 822 break; 823 case ServiceState.RIL_RADIO_TECHNOLOGY_LTE: 824 case ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA: 825 sizes = TCP_BUFFER_SIZES_LTE; 826 break; 827 case ServiceState.RIL_RADIO_TECHNOLOGY_HSPAP: 828 sizes = TCP_BUFFER_SIZES_HSPAP; 829 break; 830 default: 831 // Leave empty - this will let ConnectivityService use the system default. 832 break; 833 } 834 } 835 mLinkProperties.setTcpBufferSizes(sizes); 836 } 837 838 /** 839 * Indicates if when this connection was established we had a restricted/privileged 840 * NetworkRequest and needed it to overcome data-enabled limitations. 841 * 842 * This gets set once per connection setup and is based on conditions at that time. 843 * We could theoretically have dynamic capabilities but now is not a good time to 844 * experiement with that. 845 * 846 * This flag overrides the APN-based restriction capability, restricting the network 847 * based on both having a NetworkRequest with restricted AND needing a restricted 848 * bit to overcome user-disabled status. This allows us to handle the common case 849 * of having both restricted requests and unrestricted requests for the same apn: 850 * if conditions require a restricted network to overcome user-disabled then it must 851 * be restricted, otherwise it is unrestricted (or restricted based on APN type). 852 * 853 * Because we're not supporting dynamic capabilities, if conditions change and we go from 854 * data-enabled to not or vice-versa we will need to tear down networks to deal with it 855 * at connection setup time with the new state. 856 * 857 * This supports a privileged app bringing up a network without general apps having access 858 * to it when the network is otherwise unavailable (hipri). The first use case is 859 * pre-paid SIM reprovisioning over internet, where the carrier insists on no traffic 860 * other than from the privileged carrier-app. 861 */ 862 private boolean mRestrictedNetworkOverride = false; 863 864 // Should be called once when the call goes active to examine the state of things and 865 // declare the restriction override for the life of the connection 866 private void setNetworkRestriction() { 867 mRestrictedNetworkOverride = false; 868 // first, if we have no restricted requests, this override can stay FALSE: 869 boolean noRestrictedRequests = true; 870 for (ApnContext apnContext : mApnContexts.keySet()) { 871 noRestrictedRequests &= apnContext.hasNoRestrictedRequests(true /* exclude DUN */); 872 } 873 if (noRestrictedRequests) { 874 return; 875 } 876 877 // Do we need a restricted network to satisfy the request? 878 // Is this network metered? If not, then don't add restricted 879 if (!mApnSetting.isMetered(mPhone.getContext(), mPhone.getSubId(), 880 mPhone.getServiceState().getDataRoaming())) { 881 return; 882 } 883 884 // Is data disabled? 885 mRestrictedNetworkOverride = (mDct.isDataEnabled(true) == false); 886 } 887 888 private NetworkCapabilities makeNetworkCapabilities() { 889 NetworkCapabilities result = new NetworkCapabilities(); 890 result.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR); 891 892 if (mApnSetting != null) { 893 for (String type : mApnSetting.types) { 894 switch (type) { 895 case PhoneConstants.APN_TYPE_ALL: { 896 result.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); 897 result.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS); 898 result.addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL); 899 result.addCapability(NetworkCapabilities.NET_CAPABILITY_FOTA); 900 result.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS); 901 result.addCapability(NetworkCapabilities.NET_CAPABILITY_CBS); 902 result.addCapability(NetworkCapabilities.NET_CAPABILITY_IA); 903 break; 904 } 905 case PhoneConstants.APN_TYPE_DEFAULT: { 906 result.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); 907 break; 908 } 909 case PhoneConstants.APN_TYPE_MMS: { 910 result.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS); 911 break; 912 } 913 case PhoneConstants.APN_TYPE_SUPL: { 914 result.addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL); 915 break; 916 } 917 case PhoneConstants.APN_TYPE_DUN: { 918 ApnSetting securedDunApn = mDct.fetchDunApn(); 919 if (securedDunApn == null || securedDunApn.equals(mApnSetting)) { 920 result.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN); 921 } 922 break; 923 } 924 case PhoneConstants.APN_TYPE_FOTA: { 925 result.addCapability(NetworkCapabilities.NET_CAPABILITY_FOTA); 926 break; 927 } 928 case PhoneConstants.APN_TYPE_IMS: { 929 result.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS); 930 break; 931 } 932 case PhoneConstants.APN_TYPE_CBS: { 933 result.addCapability(NetworkCapabilities.NET_CAPABILITY_CBS); 934 break; 935 } 936 case PhoneConstants.APN_TYPE_IA: { 937 result.addCapability(NetworkCapabilities.NET_CAPABILITY_IA); 938 break; 939 } 940 case PhoneConstants.APN_TYPE_EMERGENCY: { 941 result.addCapability(NetworkCapabilities.NET_CAPABILITY_EIMS); 942 break; 943 } 944 default: 945 } 946 } 947 948 // If none of the APN types associated with this APN setting is metered, 949 // then we apply NOT_METERED capability to the network. 950 if (!mApnSetting.isMetered(mPhone.getContext(), mPhone.getSubId(), 951 mPhone.getServiceState().getDataRoaming())) { 952 result.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); 953 mNetworkInfo.setMetered(false); 954 } else { 955 result.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); 956 mNetworkInfo.setMetered(true); 957 } 958 959 result.maybeMarkCapabilitiesRestricted(); 960 } 961 if (mRestrictedNetworkOverride) { 962 result.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); 963 // don't use dun on restriction-overriden networks. 964 result.removeCapability(NetworkCapabilities.NET_CAPABILITY_DUN); 965 } 966 967 int up = 14; 968 int down = 14; 969 switch (mRilRat) { 970 case ServiceState.RIL_RADIO_TECHNOLOGY_GPRS: up = 80; down = 80; break; 971 case ServiceState.RIL_RADIO_TECHNOLOGY_EDGE: up = 59; down = 236; break; 972 case ServiceState.RIL_RADIO_TECHNOLOGY_UMTS: up = 384; down = 384; break; 973 case ServiceState.RIL_RADIO_TECHNOLOGY_IS95A: // fall through 974 case ServiceState.RIL_RADIO_TECHNOLOGY_IS95B: up = 14; down = 14; break; 975 case ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0: up = 153; down = 2457; break; 976 case ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A: up = 1843; down = 3174; break; 977 case ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT: up = 100; down = 100; break; 978 case ServiceState.RIL_RADIO_TECHNOLOGY_HSDPA: up = 2048; down = 14336; break; 979 case ServiceState.RIL_RADIO_TECHNOLOGY_HSUPA: up = 5898; down = 14336; break; 980 case ServiceState.RIL_RADIO_TECHNOLOGY_HSPA: up = 5898; down = 14336; break; 981 case ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_B: up = 1843; down = 5017; break; 982 case ServiceState.RIL_RADIO_TECHNOLOGY_LTE: up = 51200; down = 102400; break; 983 case ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA: up = 51200; down = 102400; break; 984 case ServiceState.RIL_RADIO_TECHNOLOGY_EHRPD: up = 153; down = 2516; break; 985 case ServiceState.RIL_RADIO_TECHNOLOGY_HSPAP: up = 11264; down = 43008; break; 986 default: 987 } 988 result.setLinkUpstreamBandwidthKbps(up); 989 result.setLinkDownstreamBandwidthKbps(down); 990 991 result.setNetworkSpecifier(Integer.toString(mPhone.getSubId())); 992 993 return result; 994 } 995 996 private boolean isIpAddress(String address) { 997 if (address == null) return false; 998 999 return Patterns.IP_ADDRESS.matcher(address).matches(); 1000 } 1001 1002 private DataCallResponse.SetupResult setLinkProperties(DataCallResponse response, 1003 LinkProperties lp) { 1004 // Check if system property dns usable 1005 boolean okToUseSystemPropertyDns = false; 1006 String propertyPrefix = "net." + response.ifname + "."; 1007 String dnsServers[] = new String[2]; 1008 dnsServers[0] = SystemProperties.get(propertyPrefix + "dns1"); 1009 dnsServers[1] = SystemProperties.get(propertyPrefix + "dns2"); 1010 okToUseSystemPropertyDns = isDnsOk(dnsServers); 1011 1012 // set link properties based on data call response 1013 return response.setLinkProperties(lp, okToUseSystemPropertyDns); 1014 } 1015 1016 /** 1017 * Initialize connection, this will fail if the 1018 * apnSettings are not compatible. 1019 * 1020 * @param cp the Connection parameters 1021 * @return true if initialization was successful. 1022 */ 1023 private boolean initConnection(ConnectionParams cp) { 1024 ApnContext apnContext = cp.mApnContext; 1025 if (mApnSetting == null) { 1026 // Only change apn setting if it isn't set, it will 1027 // only NOT be set only if we're in DcInactiveState. 1028 mApnSetting = apnContext.getApnSetting(); 1029 } 1030 if (mApnSetting == null || !mApnSetting.canHandleType(apnContext.getApnType())) { 1031 if (DBG) { 1032 log("initConnection: incompatible apnSetting in ConnectionParams cp=" + cp 1033 + " dc=" + DataConnection.this); 1034 } 1035 return false; 1036 } 1037 mTag += 1; 1038 mConnectionParams = cp; 1039 mConnectionParams.mTag = mTag; 1040 1041 // always update the ConnectionParams with the latest or the 1042 // connectionGeneration gets stale 1043 mApnContexts.put(apnContext, cp); 1044 1045 if (DBG) { 1046 log("initConnection: " 1047 + " RefCount=" + mApnContexts.size() 1048 + " mApnList=" + mApnContexts 1049 + " mConnectionParams=" + mConnectionParams); 1050 } 1051 return true; 1052 } 1053 1054 /** 1055 * The parent state for all other states. 1056 */ 1057 private class DcDefaultState extends State { 1058 @Override 1059 public void enter() { 1060 if (DBG) log("DcDefaultState: enter"); 1061 1062 // Register for DRS or RAT change 1063 mPhone.getServiceStateTracker().registerForDataRegStateOrRatChanged(getHandler(), 1064 DataConnection.EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED, null); 1065 1066 mPhone.getServiceStateTracker().registerForDataRoamingOn(getHandler(), 1067 DataConnection.EVENT_DATA_CONNECTION_ROAM_ON, null); 1068 mPhone.getServiceStateTracker().registerForDataRoamingOff(getHandler(), 1069 DataConnection.EVENT_DATA_CONNECTION_ROAM_OFF, null); 1070 1071 // Add ourselves to the list of data connections 1072 mDcController.addDc(DataConnection.this); 1073 } 1074 @Override 1075 public void exit() { 1076 if (DBG) log("DcDefaultState: exit"); 1077 1078 // Unregister for DRS or RAT change. 1079 mPhone.getServiceStateTracker().unregisterForDataRegStateOrRatChanged(getHandler()); 1080 1081 mPhone.getServiceStateTracker().unregisterForDataRoamingOn(getHandler()); 1082 mPhone.getServiceStateTracker().unregisterForDataRoamingOff(getHandler()); 1083 1084 // Remove ourselves from the DC lists 1085 mDcController.removeDc(DataConnection.this); 1086 1087 if (mAc != null) { 1088 mAc.disconnected(); 1089 mAc = null; 1090 } 1091 mApnContexts = null; 1092 mReconnectIntent = null; 1093 mDct = null; 1094 mApnSetting = null; 1095 mPhone = null; 1096 mLinkProperties = null; 1097 mLastFailCause = null; 1098 mUserData = null; 1099 mDcController = null; 1100 mDcTesterFailBringUpAll = null; 1101 } 1102 1103 @Override 1104 public boolean processMessage(Message msg) { 1105 boolean retVal = HANDLED; 1106 1107 if (VDBG) { 1108 log("DcDefault msg=" + getWhatToString(msg.what) 1109 + " RefCount=" + mApnContexts.size()); 1110 } 1111 switch (msg.what) { 1112 case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: { 1113 if (mAc != null) { 1114 if (VDBG) log("Disconnecting to previous connection mAc=" + mAc); 1115 mAc.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED, 1116 AsyncChannel.STATUS_FULL_CONNECTION_REFUSED_ALREADY_CONNECTED); 1117 } else { 1118 mAc = new AsyncChannel(); 1119 mAc.connected(null, getHandler(), msg.replyTo); 1120 if (VDBG) log("DcDefaultState: FULL_CONNECTION reply connected"); 1121 mAc.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED, 1122 AsyncChannel.STATUS_SUCCESSFUL, mId, "hi"); 1123 } 1124 break; 1125 } 1126 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: { 1127 if (DBG) { 1128 log("DcDefault: CMD_CHANNEL_DISCONNECTED before quiting call dump"); 1129 dumpToLog(); 1130 } 1131 1132 quit(); 1133 break; 1134 } 1135 case DcAsyncChannel.REQ_IS_INACTIVE: { 1136 boolean val = getIsInactive(); 1137 if (VDBG) log("REQ_IS_INACTIVE isInactive=" + val); 1138 mAc.replyToMessage(msg, DcAsyncChannel.RSP_IS_INACTIVE, val ? 1 : 0); 1139 break; 1140 } 1141 case DcAsyncChannel.REQ_GET_CID: { 1142 int cid = getCid(); 1143 if (VDBG) log("REQ_GET_CID cid=" + cid); 1144 mAc.replyToMessage(msg, DcAsyncChannel.RSP_GET_CID, cid); 1145 break; 1146 } 1147 case DcAsyncChannel.REQ_GET_APNSETTING: { 1148 ApnSetting apnSetting = getApnSetting(); 1149 if (VDBG) log("REQ_GET_APNSETTING mApnSetting=" + apnSetting); 1150 mAc.replyToMessage(msg, DcAsyncChannel.RSP_GET_APNSETTING, apnSetting); 1151 break; 1152 } 1153 case DcAsyncChannel.REQ_GET_LINK_PROPERTIES: { 1154 LinkProperties lp = getCopyLinkProperties(); 1155 if (VDBG) log("REQ_GET_LINK_PROPERTIES linkProperties" + lp); 1156 mAc.replyToMessage(msg, DcAsyncChannel.RSP_GET_LINK_PROPERTIES, lp); 1157 break; 1158 } 1159 case DcAsyncChannel.REQ_SET_LINK_PROPERTIES_HTTP_PROXY: { 1160 ProxyInfo proxy = (ProxyInfo) msg.obj; 1161 if (VDBG) log("REQ_SET_LINK_PROPERTIES_HTTP_PROXY proxy=" + proxy); 1162 setLinkPropertiesHttpProxy(proxy); 1163 mAc.replyToMessage(msg, DcAsyncChannel.RSP_SET_LINK_PROPERTIES_HTTP_PROXY); 1164 if (mNetworkAgent != null) { 1165 mNetworkAgent.sendLinkProperties(mLinkProperties); 1166 } 1167 break; 1168 } 1169 case DcAsyncChannel.REQ_GET_NETWORK_CAPABILITIES: { 1170 NetworkCapabilities nc = getCopyNetworkCapabilities(); 1171 if (VDBG) log("REQ_GET_NETWORK_CAPABILITIES networkCapabilities" + nc); 1172 mAc.replyToMessage(msg, DcAsyncChannel.RSP_GET_NETWORK_CAPABILITIES, nc); 1173 break; 1174 } 1175 case DcAsyncChannel.REQ_RESET: 1176 if (VDBG) log("DcDefaultState: msg.what=REQ_RESET"); 1177 transitionTo(mInactiveState); 1178 break; 1179 case EVENT_CONNECT: 1180 if (DBG) log("DcDefaultState: msg.what=EVENT_CONNECT, fail not expected"); 1181 ConnectionParams cp = (ConnectionParams) msg.obj; 1182 notifyConnectCompleted(cp, DcFailCause.UNKNOWN, false); 1183 break; 1184 1185 case EVENT_DISCONNECT: 1186 if (DBG) { 1187 log("DcDefaultState deferring msg.what=EVENT_DISCONNECT RefCount=" 1188 + mApnContexts.size()); 1189 } 1190 deferMessage(msg); 1191 break; 1192 1193 case EVENT_DISCONNECT_ALL: 1194 if (DBG) { 1195 log("DcDefaultState deferring msg.what=EVENT_DISCONNECT_ALL RefCount=" 1196 + mApnContexts.size()); 1197 } 1198 deferMessage(msg); 1199 break; 1200 1201 case EVENT_TEAR_DOWN_NOW: 1202 if (DBG) log("DcDefaultState EVENT_TEAR_DOWN_NOW"); 1203 mPhone.mCi.deactivateDataCall(mCid, 0, null); 1204 break; 1205 1206 case EVENT_LOST_CONNECTION: 1207 if (DBG) { 1208 String s = "DcDefaultState ignore EVENT_LOST_CONNECTION" 1209 + " tag=" + msg.arg1 + ":mTag=" + mTag; 1210 logAndAddLogRec(s); 1211 } 1212 break; 1213 case EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED: 1214 AsyncResult ar = (AsyncResult)msg.obj; 1215 Pair<Integer, Integer> drsRatPair = (Pair<Integer, Integer>)ar.result; 1216 mDataRegState = drsRatPair.first; 1217 if (mRilRat != drsRatPair.second) { 1218 updateTcpBufferSizes(drsRatPair.second); 1219 } 1220 mRilRat = drsRatPair.second; 1221 if (DBG) { 1222 log("DcDefaultState: EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED" 1223 + " drs=" + mDataRegState 1224 + " mRilRat=" + mRilRat); 1225 } 1226 ServiceState ss = mPhone.getServiceState(); 1227 int networkType = ss.getDataNetworkType(); 1228 mNetworkInfo.setSubtype(networkType, 1229 TelephonyManager.getNetworkTypeName(networkType)); 1230 if (mNetworkAgent != null) { 1231 updateNetworkInfoSuspendState(); 1232 mNetworkAgent.sendNetworkCapabilities(makeNetworkCapabilities()); 1233 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 1234 mNetworkAgent.sendLinkProperties(mLinkProperties); 1235 } 1236 break; 1237 1238 case EVENT_DATA_CONNECTION_ROAM_ON: 1239 mNetworkInfo.setRoaming(true); 1240 break; 1241 1242 case EVENT_DATA_CONNECTION_ROAM_OFF: 1243 mNetworkInfo.setRoaming(false); 1244 break; 1245 1246 default: 1247 if (DBG) { 1248 log("DcDefaultState: shouldn't happen but ignore msg.what=" 1249 + getWhatToString(msg.what)); 1250 } 1251 break; 1252 } 1253 1254 return retVal; 1255 } 1256 } 1257 1258 private boolean updateNetworkInfoSuspendState() { 1259 final NetworkInfo.DetailedState oldState = mNetworkInfo.getDetailedState(); 1260 1261 // this is only called when we are either connected or suspended. Decide which. 1262 if (mNetworkAgent == null) { 1263 Rlog.e(getName(), "Setting suspend state without a NetworkAgent"); 1264 } 1265 1266 // if we are not in-service change to SUSPENDED 1267 final ServiceStateTracker sst = mPhone.getServiceStateTracker(); 1268 if (sst.getCurrentDataConnectionState() != ServiceState.STATE_IN_SERVICE) { 1269 mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.SUSPENDED, null, 1270 mNetworkInfo.getExtraInfo()); 1271 } else { 1272 // check for voice call and concurrency issues 1273 if (sst.isConcurrentVoiceAndDataAllowed() == false) { 1274 final CallTracker ct = mPhone.getCallTracker(); 1275 if (ct.getState() != PhoneConstants.State.IDLE) { 1276 mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.SUSPENDED, null, 1277 mNetworkInfo.getExtraInfo()); 1278 return (oldState != NetworkInfo.DetailedState.SUSPENDED); 1279 } 1280 } 1281 mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null, 1282 mNetworkInfo.getExtraInfo()); 1283 } 1284 return (oldState != mNetworkInfo.getDetailedState()); 1285 } 1286 1287 private DcDefaultState mDefaultState = new DcDefaultState(); 1288 1289 /** 1290 * The state machine is inactive and expects a EVENT_CONNECT. 1291 */ 1292 private class DcInactiveState extends State { 1293 // Inform all contexts we've failed connecting 1294 public void setEnterNotificationParams(ConnectionParams cp, DcFailCause cause) { 1295 if (VDBG) log("DcInactiveState: setEnterNotificationParams cp,cause"); 1296 mConnectionParams = cp; 1297 mDisconnectParams = null; 1298 mDcFailCause = cause; 1299 } 1300 1301 // Inform all contexts we've failed disconnected 1302 public void setEnterNotificationParams(DisconnectParams dp) { 1303 if (VDBG) log("DcInactiveState: setEnterNotificationParams dp"); 1304 mConnectionParams = null; 1305 mDisconnectParams = dp; 1306 mDcFailCause = DcFailCause.NONE; 1307 } 1308 1309 // Inform all contexts of the failure cause 1310 public void setEnterNotificationParams(DcFailCause cause) { 1311 mConnectionParams = null; 1312 mDisconnectParams = null; 1313 mDcFailCause = cause; 1314 } 1315 1316 @Override 1317 public void enter() { 1318 mTag += 1; 1319 if (DBG) log("DcInactiveState: enter() mTag=" + mTag); 1320 1321 if (mConnectionParams != null) { 1322 if (DBG) { 1323 log("DcInactiveState: enter notifyConnectCompleted +ALL failCause=" 1324 + mDcFailCause); 1325 } 1326 notifyConnectCompleted(mConnectionParams, mDcFailCause, true); 1327 } 1328 if (mDisconnectParams != null) { 1329 if (DBG) { 1330 log("DcInactiveState: enter notifyDisconnectCompleted +ALL failCause=" 1331 + mDcFailCause); 1332 } 1333 notifyDisconnectCompleted(mDisconnectParams, true); 1334 } 1335 if (mDisconnectParams == null && mConnectionParams == null && mDcFailCause != null) { 1336 if (DBG) { 1337 log("DcInactiveState: enter notifyAllDisconnectCompleted failCause=" 1338 + mDcFailCause); 1339 } 1340 notifyAllDisconnectCompleted(mDcFailCause); 1341 } 1342 1343 // Remove ourselves from cid mapping, before clearSettings 1344 mDcController.removeActiveDcByCid(DataConnection.this); 1345 1346 clearSettings(); 1347 } 1348 1349 @Override 1350 public void exit() { 1351 } 1352 1353 @Override 1354 public boolean processMessage(Message msg) { 1355 boolean retVal; 1356 1357 switch (msg.what) { 1358 case DcAsyncChannel.REQ_RESET: 1359 if (DBG) { 1360 log("DcInactiveState: msg.what=RSP_RESET, ignore we're already reset"); 1361 } 1362 retVal = HANDLED; 1363 break; 1364 1365 case EVENT_CONNECT: 1366 if (DBG) log("DcInactiveState: mag.what=EVENT_CONNECT"); 1367 ConnectionParams cp = (ConnectionParams) msg.obj; 1368 if (initConnection(cp)) { 1369 onConnect(mConnectionParams); 1370 transitionTo(mActivatingState); 1371 } else { 1372 if (DBG) { 1373 log("DcInactiveState: msg.what=EVENT_CONNECT initConnection failed"); 1374 } 1375 notifyConnectCompleted(cp, DcFailCause.UNACCEPTABLE_NETWORK_PARAMETER, 1376 false); 1377 } 1378 retVal = HANDLED; 1379 break; 1380 1381 case EVENT_DISCONNECT: 1382 if (DBG) log("DcInactiveState: msg.what=EVENT_DISCONNECT"); 1383 notifyDisconnectCompleted((DisconnectParams)msg.obj, false); 1384 retVal = HANDLED; 1385 break; 1386 1387 case EVENT_DISCONNECT_ALL: 1388 if (DBG) log("DcInactiveState: msg.what=EVENT_DISCONNECT_ALL"); 1389 notifyDisconnectCompleted((DisconnectParams)msg.obj, false); 1390 retVal = HANDLED; 1391 break; 1392 1393 default: 1394 if (VDBG) { 1395 log("DcInactiveState nothandled msg.what=" + getWhatToString(msg.what)); 1396 } 1397 retVal = NOT_HANDLED; 1398 break; 1399 } 1400 return retVal; 1401 } 1402 } 1403 private DcInactiveState mInactiveState = new DcInactiveState(); 1404 1405 /** 1406 * The state machine is activating a connection. 1407 */ 1408 private class DcActivatingState extends State { 1409 @Override 1410 public boolean processMessage(Message msg) { 1411 boolean retVal; 1412 AsyncResult ar; 1413 ConnectionParams cp; 1414 1415 if (DBG) log("DcActivatingState: msg=" + msgToString(msg)); 1416 switch (msg.what) { 1417 case EVENT_DATA_CONNECTION_DRS_OR_RAT_CHANGED: 1418 case EVENT_CONNECT: 1419 // Activating can't process until we're done. 1420 deferMessage(msg); 1421 retVal = HANDLED; 1422 break; 1423 1424 case EVENT_SETUP_DATA_CONNECTION_DONE: 1425 ar = (AsyncResult) msg.obj; 1426 cp = (ConnectionParams) ar.userObj; 1427 1428 DataCallResponse.SetupResult result = onSetupConnectionCompleted(ar); 1429 if (result != DataCallResponse.SetupResult.ERR_Stale) { 1430 if (mConnectionParams != cp) { 1431 loge("DcActivatingState: WEIRD mConnectionsParams:"+ mConnectionParams 1432 + " != cp:" + cp); 1433 } 1434 } 1435 if (DBG) { 1436 log("DcActivatingState onSetupConnectionCompleted result=" + result 1437 + " dc=" + DataConnection.this); 1438 } 1439 if (cp.mApnContext != null) { 1440 cp.mApnContext.requestLog("onSetupConnectionCompleted result=" + result); 1441 } 1442 switch (result) { 1443 case SUCCESS: 1444 // All is well 1445 mDcFailCause = DcFailCause.NONE; 1446 transitionTo(mActiveState); 1447 break; 1448 case ERR_BadCommand: 1449 // Vendor ril rejected the command and didn't connect. 1450 // Transition to inactive but send notifications after 1451 // we've entered the mInactive state. 1452 mInactiveState.setEnterNotificationParams(cp, result.mFailCause); 1453 transitionTo(mInactiveState); 1454 break; 1455 case ERR_UnacceptableParameter: 1456 // The addresses given from the RIL are bad 1457 tearDownData(cp); 1458 transitionTo(mDisconnectingErrorCreatingConnection); 1459 break; 1460 case ERR_GetLastErrorFromRil: 1461 // Request failed and this is an old RIL 1462 mPhone.mCi.getLastDataCallFailCause( 1463 obtainMessage(EVENT_GET_LAST_FAIL_DONE, cp)); 1464 break; 1465 case ERR_RilError: 1466 1467 // Retrieve the suggested retry delay from the modem and save it. 1468 // If the modem want us to retry the current APN again, it will 1469 // suggest a positive delay value (in milliseconds). Otherwise we'll get 1470 // NO_SUGGESTED_RETRY_DELAY here. 1471 long delay = getSuggestedRetryDelay(ar); 1472 cp.mApnContext.setModemSuggestedDelay(delay); 1473 1474 String str = "DcActivatingState: ERR_RilError " 1475 + " delay=" + delay 1476 + " result=" + result 1477 + " result.isRestartRadioFail=" + 1478 result.mFailCause.isRestartRadioFail() 1479 + " result.isPermanentFail=" + 1480 mDct.isPermanentFail(result.mFailCause); 1481 if (DBG) log(str); 1482 if (cp.mApnContext != null) cp.mApnContext.requestLog(str); 1483 1484 // Save the cause. DcTracker.onDataSetupComplete will check this 1485 // failure cause and determine if we need to retry this APN later 1486 // or not. 1487 mInactiveState.setEnterNotificationParams(cp, result.mFailCause); 1488 transitionTo(mInactiveState); 1489 break; 1490 case ERR_Stale: 1491 loge("DcActivatingState: stale EVENT_SETUP_DATA_CONNECTION_DONE" 1492 + " tag:" + cp.mTag + " != mTag:" + mTag); 1493 break; 1494 default: 1495 throw new RuntimeException("Unknown SetupResult, should not happen"); 1496 } 1497 retVal = HANDLED; 1498 break; 1499 1500 case EVENT_GET_LAST_FAIL_DONE: 1501 ar = (AsyncResult) msg.obj; 1502 cp = (ConnectionParams) ar.userObj; 1503 if (cp.mTag == mTag) { 1504 if (mConnectionParams != cp) { 1505 loge("DcActivatingState: WEIRD mConnectionsParams:" + mConnectionParams 1506 + " != cp:" + cp); 1507 } 1508 1509 DcFailCause cause = DcFailCause.UNKNOWN; 1510 1511 if (ar.exception == null) { 1512 int rilFailCause = ((int[]) (ar.result))[0]; 1513 cause = DcFailCause.fromInt(rilFailCause); 1514 if (cause == DcFailCause.NONE) { 1515 if (DBG) { 1516 log("DcActivatingState msg.what=EVENT_GET_LAST_FAIL_DONE" 1517 + " BAD: error was NONE, change to UNKNOWN"); 1518 } 1519 cause = DcFailCause.UNKNOWN; 1520 } 1521 } 1522 mDcFailCause = cause; 1523 1524 if (DBG) { 1525 log("DcActivatingState msg.what=EVENT_GET_LAST_FAIL_DONE" 1526 + " cause=" + cause + " dc=" + DataConnection.this); 1527 } 1528 1529 mInactiveState.setEnterNotificationParams(cp, cause); 1530 transitionTo(mInactiveState); 1531 } else { 1532 loge("DcActivatingState: stale EVENT_GET_LAST_FAIL_DONE" 1533 + " tag:" + cp.mTag + " != mTag:" + mTag); 1534 } 1535 1536 retVal = HANDLED; 1537 break; 1538 1539 default: 1540 if (VDBG) { 1541 log("DcActivatingState not handled msg.what=" + 1542 getWhatToString(msg.what) + " RefCount=" + mApnContexts.size()); 1543 } 1544 retVal = NOT_HANDLED; 1545 break; 1546 } 1547 return retVal; 1548 } 1549 } 1550 private DcActivatingState mActivatingState = new DcActivatingState(); 1551 1552 /** 1553 * The state machine is connected, expecting an EVENT_DISCONNECT. 1554 */ 1555 private class DcActiveState extends State { 1556 @Override public void enter() { 1557 if (DBG) log("DcActiveState: enter dc=" + DataConnection.this); 1558 1559 // verify and get updated information in case these things 1560 // are obsolete 1561 { 1562 ServiceState ss = mPhone.getServiceState(); 1563 final int networkType = ss.getDataNetworkType(); 1564 if (mNetworkInfo.getSubtype() != networkType) { 1565 log("DcActiveState with incorrect subtype (" + mNetworkInfo.getSubtype() + 1566 ", " + networkType + "), updating."); 1567 } 1568 mNetworkInfo.setSubtype(networkType, TelephonyManager.getNetworkTypeName(networkType)); 1569 final boolean roaming = ss.getDataRoaming(); 1570 if (roaming != mNetworkInfo.isRoaming()) { 1571 log("DcActiveState with incorrect roaming (" + mNetworkInfo.isRoaming() + 1572 ", " + roaming +"), updating."); 1573 } 1574 mNetworkInfo.setRoaming(roaming); 1575 } 1576 1577 boolean createNetworkAgent = true; 1578 // If a disconnect is already pending, avoid notifying all of connected 1579 if (hasMessages(EVENT_DISCONNECT) || 1580 hasMessages(EVENT_DISCONNECT_ALL) || 1581 hasDeferredMessages(EVENT_DISCONNECT) || 1582 hasDeferredMessages(EVENT_DISCONNECT_ALL)) { 1583 log("DcActiveState: skipping notifyAllOfConnected()"); 1584 createNetworkAgent = false; 1585 } else { 1586 // If we were retrying there maybe more than one, otherwise they'll only be one. 1587 notifyAllOfConnected(Phone.REASON_CONNECTED); 1588 } 1589 1590 mPhone.getCallTracker().registerForVoiceCallStarted(getHandler(), 1591 DataConnection.EVENT_DATA_CONNECTION_VOICE_CALL_STARTED, null); 1592 mPhone.getCallTracker().registerForVoiceCallEnded(getHandler(), 1593 DataConnection.EVENT_DATA_CONNECTION_VOICE_CALL_ENDED, null); 1594 1595 // If the EVENT_CONNECT set the current max retry restore it here 1596 // if it didn't then this is effectively a NOP. 1597 mDcController.addActiveDcByCid(DataConnection.this); 1598 1599 mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, 1600 mNetworkInfo.getReason(), null); 1601 mNetworkInfo.setExtraInfo(mApnSetting.apn); 1602 updateTcpBufferSizes(mRilRat); 1603 1604 final NetworkMisc misc = new NetworkMisc(); 1605 final CarrierSignalAgent carrierSignalAgent = mPhone.getCarrierSignalAgent(); 1606 if(carrierSignalAgent.hasRegisteredCarrierSignalReceivers()) { 1607 // carrierSignal Receivers will place the carrier-specific provisioning notification 1608 misc.provisioningNotificationDisabled = true; 1609 } 1610 misc.subscriberId = mPhone.getSubscriberId(); 1611 1612 if (createNetworkAgent) { 1613 setNetworkRestriction(); 1614 mNetworkAgent = new DcNetworkAgent(getHandler().getLooper(), mPhone.getContext(), 1615 "DcNetworkAgent", mNetworkInfo, makeNetworkCapabilities(), mLinkProperties, 1616 50, misc); 1617 } 1618 } 1619 1620 @Override 1621 public void exit() { 1622 if (DBG) log("DcActiveState: exit dc=" + this); 1623 String reason = mNetworkInfo.getReason(); 1624 if(mDcController.isExecutingCarrierChange()) { 1625 reason = Phone.REASON_CARRIER_CHANGE; 1626 } else if (mDisconnectParams != null && mDisconnectParams.mReason != null) { 1627 reason = mDisconnectParams.mReason; 1628 } else if (mDcFailCause != null) { 1629 reason = mDcFailCause.toString(); 1630 } 1631 mPhone.getCallTracker().unregisterForVoiceCallStarted(getHandler()); 1632 mPhone.getCallTracker().unregisterForVoiceCallEnded(getHandler()); 1633 1634 mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, 1635 reason, mNetworkInfo.getExtraInfo()); 1636 if (mNetworkAgent != null) { 1637 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 1638 mNetworkAgent = null; 1639 } 1640 } 1641 1642 @Override 1643 public boolean processMessage(Message msg) { 1644 boolean retVal; 1645 1646 switch (msg.what) { 1647 case EVENT_CONNECT: { 1648 ConnectionParams cp = (ConnectionParams) msg.obj; 1649 // either add this new apn context to our set or 1650 // update the existing cp with the latest connection generation number 1651 mApnContexts.put(cp.mApnContext, cp); 1652 if (DBG) { 1653 log("DcActiveState: EVENT_CONNECT cp=" + cp + " dc=" + DataConnection.this); 1654 } 1655 notifyConnectCompleted(cp, DcFailCause.NONE, false); 1656 retVal = HANDLED; 1657 break; 1658 } 1659 case EVENT_DISCONNECT: { 1660 DisconnectParams dp = (DisconnectParams) msg.obj; 1661 if (DBG) { 1662 log("DcActiveState: EVENT_DISCONNECT dp=" + dp 1663 + " dc=" + DataConnection.this); 1664 } 1665 if (mApnContexts.containsKey(dp.mApnContext)) { 1666 if (DBG) { 1667 log("DcActiveState msg.what=EVENT_DISCONNECT RefCount=" 1668 + mApnContexts.size()); 1669 } 1670 1671 if (mApnContexts.size() == 1) { 1672 mApnContexts.clear(); 1673 mDisconnectParams = dp; 1674 mConnectionParams = null; 1675 dp.mTag = mTag; 1676 tearDownData(dp); 1677 transitionTo(mDisconnectingState); 1678 } else { 1679 mApnContexts.remove(dp.mApnContext); 1680 notifyDisconnectCompleted(dp, false); 1681 } 1682 } else { 1683 log("DcActiveState ERROR no such apnContext=" + dp.mApnContext 1684 + " in this dc=" + DataConnection.this); 1685 notifyDisconnectCompleted(dp, false); 1686 } 1687 retVal = HANDLED; 1688 break; 1689 } 1690 case EVENT_DISCONNECT_ALL: { 1691 if (DBG) { 1692 log("DcActiveState EVENT_DISCONNECT clearing apn contexts," 1693 + " dc=" + DataConnection.this); 1694 } 1695 DisconnectParams dp = (DisconnectParams) msg.obj; 1696 mDisconnectParams = dp; 1697 mConnectionParams = null; 1698 dp.mTag = mTag; 1699 tearDownData(dp); 1700 transitionTo(mDisconnectingState); 1701 retVal = HANDLED; 1702 break; 1703 } 1704 case EVENT_LOST_CONNECTION: { 1705 if (DBG) { 1706 log("DcActiveState EVENT_LOST_CONNECTION dc=" + DataConnection.this); 1707 } 1708 1709 mInactiveState.setEnterNotificationParams(DcFailCause.LOST_CONNECTION); 1710 transitionTo(mInactiveState); 1711 retVal = HANDLED; 1712 break; 1713 } 1714 case EVENT_DATA_CONNECTION_ROAM_ON: { 1715 mNetworkInfo.setRoaming(true); 1716 if (mNetworkAgent != null) { 1717 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 1718 } 1719 retVal = HANDLED; 1720 break; 1721 } 1722 case EVENT_DATA_CONNECTION_ROAM_OFF: { 1723 mNetworkInfo.setRoaming(false); 1724 if (mNetworkAgent != null) { 1725 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 1726 } 1727 retVal = HANDLED; 1728 break; 1729 } 1730 case EVENT_BW_REFRESH_RESPONSE: { 1731 AsyncResult ar = (AsyncResult)msg.obj; 1732 if (ar.exception != null) { 1733 log("EVENT_BW_REFRESH_RESPONSE: error ignoring, e=" + ar.exception); 1734 } else { 1735 final ArrayList<Integer> capInfo = (ArrayList<Integer>)ar.result; 1736 final int lceBwDownKbps = capInfo.get(0); 1737 NetworkCapabilities nc = makeNetworkCapabilities(); 1738 if (mPhone.getLceStatus() == RILConstants.LCE_ACTIVE) { 1739 nc.setLinkDownstreamBandwidthKbps(lceBwDownKbps); 1740 if (mNetworkAgent != null) { 1741 mNetworkAgent.sendNetworkCapabilities(nc); 1742 } 1743 } 1744 } 1745 retVal = HANDLED; 1746 break; 1747 } 1748 case EVENT_DATA_CONNECTION_VOICE_CALL_STARTED: 1749 case EVENT_DATA_CONNECTION_VOICE_CALL_ENDED: { 1750 if (updateNetworkInfoSuspendState() && mNetworkAgent != null) { 1751 // state changed 1752 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 1753 } 1754 retVal = HANDLED; 1755 break; 1756 } 1757 default: 1758 if (VDBG) { 1759 log("DcActiveState not handled msg.what=" + getWhatToString(msg.what)); 1760 } 1761 retVal = NOT_HANDLED; 1762 break; 1763 } 1764 return retVal; 1765 } 1766 } 1767 private DcActiveState mActiveState = new DcActiveState(); 1768 1769 /** 1770 * The state machine is disconnecting. 1771 */ 1772 private class DcDisconnectingState extends State { 1773 @Override 1774 public boolean processMessage(Message msg) { 1775 boolean retVal; 1776 1777 switch (msg.what) { 1778 case EVENT_CONNECT: 1779 if (DBG) log("DcDisconnectingState msg.what=EVENT_CONNECT. Defer. RefCount = " 1780 + mApnContexts.size()); 1781 deferMessage(msg); 1782 retVal = HANDLED; 1783 break; 1784 1785 case EVENT_DEACTIVATE_DONE: 1786 AsyncResult ar = (AsyncResult) msg.obj; 1787 DisconnectParams dp = (DisconnectParams) ar.userObj; 1788 1789 String str = "DcDisconnectingState msg.what=EVENT_DEACTIVATE_DONE RefCount=" 1790 + mApnContexts.size(); 1791 if (DBG) log(str); 1792 if (dp.mApnContext != null) dp.mApnContext.requestLog(str); 1793 1794 if (dp.mTag == mTag) { 1795 // Transition to inactive but send notifications after 1796 // we've entered the mInactive state. 1797 mInactiveState.setEnterNotificationParams((DisconnectParams) ar.userObj); 1798 transitionTo(mInactiveState); 1799 } else { 1800 if (DBG) log("DcDisconnectState stale EVENT_DEACTIVATE_DONE" 1801 + " dp.tag=" + dp.mTag + " mTag=" + mTag); 1802 } 1803 retVal = HANDLED; 1804 break; 1805 1806 default: 1807 if (VDBG) { 1808 log("DcDisconnectingState not handled msg.what=" 1809 + getWhatToString(msg.what)); 1810 } 1811 retVal = NOT_HANDLED; 1812 break; 1813 } 1814 return retVal; 1815 } 1816 } 1817 private DcDisconnectingState mDisconnectingState = new DcDisconnectingState(); 1818 1819 /** 1820 * The state machine is disconnecting after an creating a connection. 1821 */ 1822 private class DcDisconnectionErrorCreatingConnection extends State { 1823 @Override 1824 public boolean processMessage(Message msg) { 1825 boolean retVal; 1826 1827 switch (msg.what) { 1828 case EVENT_DEACTIVATE_DONE: 1829 AsyncResult ar = (AsyncResult) msg.obj; 1830 ConnectionParams cp = (ConnectionParams) ar.userObj; 1831 if (cp.mTag == mTag) { 1832 String str = "DcDisconnectionErrorCreatingConnection" + 1833 " msg.what=EVENT_DEACTIVATE_DONE"; 1834 if (DBG) log(str); 1835 if (cp.mApnContext != null) cp.mApnContext.requestLog(str); 1836 1837 // Transition to inactive but send notifications after 1838 // we've entered the mInactive state. 1839 mInactiveState.setEnterNotificationParams(cp, 1840 DcFailCause.UNACCEPTABLE_NETWORK_PARAMETER); 1841 transitionTo(mInactiveState); 1842 } else { 1843 if (DBG) { 1844 log("DcDisconnectionErrorCreatingConnection stale EVENT_DEACTIVATE_DONE" 1845 + " dp.tag=" + cp.mTag + ", mTag=" + mTag); 1846 } 1847 } 1848 retVal = HANDLED; 1849 break; 1850 1851 default: 1852 if (VDBG) { 1853 log("DcDisconnectionErrorCreatingConnection not handled msg.what=" 1854 + getWhatToString(msg.what)); 1855 } 1856 retVal = NOT_HANDLED; 1857 break; 1858 } 1859 return retVal; 1860 } 1861 } 1862 private DcDisconnectionErrorCreatingConnection mDisconnectingErrorCreatingConnection = 1863 new DcDisconnectionErrorCreatingConnection(); 1864 1865 1866 private class DcNetworkAgent extends NetworkAgent { 1867 public DcNetworkAgent(Looper l, Context c, String TAG, NetworkInfo ni, 1868 NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) { 1869 super(l, c, TAG, ni, nc, lp, score, misc); 1870 } 1871 1872 @Override 1873 protected void unwanted() { 1874 if (mNetworkAgent != this) { 1875 log("DcNetworkAgent: unwanted found mNetworkAgent=" + mNetworkAgent + 1876 ", which isn't me. Aborting unwanted"); 1877 return; 1878 } 1879 // this can only happen if our exit has been called - we're already disconnected 1880 if (mApnContexts == null) return; 1881 for (ConnectionParams cp : mApnContexts.values()) { 1882 final ApnContext apnContext = cp.mApnContext; 1883 final Pair<ApnContext, Integer> pair = 1884 new Pair<ApnContext, Integer>(apnContext, cp.mConnectionGeneration); 1885 log("DcNetworkAgent: [unwanted]: disconnect apnContext=" + apnContext); 1886 Message msg = mDct.obtainMessage(DctConstants.EVENT_DISCONNECT_DONE, pair); 1887 DisconnectParams dp = new DisconnectParams(apnContext, apnContext.getReason(), msg); 1888 DataConnection.this.sendMessage(DataConnection.this. 1889 obtainMessage(EVENT_DISCONNECT, dp)); 1890 } 1891 } 1892 1893 @Override 1894 protected void pollLceData() { 1895 if(mPhone.getLceStatus() == RILConstants.LCE_ACTIVE) { // active LCE service 1896 mPhone.mCi.pullLceData(DataConnection.this.obtainMessage(EVENT_BW_REFRESH_RESPONSE)); 1897 } 1898 } 1899 1900 @Override 1901 protected void networkStatus(int status, String redirectUrl) { 1902 if(!TextUtils.isEmpty(redirectUrl)) { 1903 log("validation status: " + status + " with redirection URL: " + redirectUrl); 1904 /* its possible that we have multiple DataConnection with INTERNET_CAPABILITY 1905 all fail the validation with the same redirection url, send CMD back to DCTracker 1906 and let DcTracker to make the decision */ 1907 Message msg = mDct.obtainMessage(DctConstants.EVENT_REDIRECTION_DETECTED, 1908 redirectUrl); 1909 msg.sendToTarget(); 1910 } 1911 } 1912 } 1913 1914 // ******* "public" interface 1915 1916 /** 1917 * Used for testing purposes. 1918 */ 1919 /* package */ void tearDownNow() { 1920 if (DBG) log("tearDownNow()"); 1921 sendMessage(obtainMessage(EVENT_TEAR_DOWN_NOW)); 1922 } 1923 1924 /** 1925 * Using the result of the SETUP_DATA_CALL determine the retry delay. 1926 * 1927 * @param ar is the result from SETUP_DATA_CALL 1928 * @return NO_SUGGESTED_RETRY_DELAY if no retry is needed otherwise the delay to the 1929 * next SETUP_DATA_CALL 1930 */ 1931 private long getSuggestedRetryDelay(AsyncResult ar) { 1932 1933 DataCallResponse response = (DataCallResponse) ar.result; 1934 1935 /** According to ril.h 1936 * The value < 0 means no value is suggested 1937 * The value 0 means retry should be done ASAP. 1938 * The value of Integer.MAX_VALUE(0x7fffffff) means no retry. 1939 */ 1940 1941 // The value < 0 means no value is suggested 1942 if (response.suggestedRetryTime < 0) { 1943 if (DBG) log("No suggested retry delay."); 1944 return RetryManager.NO_SUGGESTED_RETRY_DELAY; 1945 } 1946 // The value of Integer.MAX_VALUE(0x7fffffff) means no retry. 1947 else if (response.suggestedRetryTime == Integer.MAX_VALUE) { 1948 if (DBG) log("Modem suggested not retrying."); 1949 return RetryManager.NO_RETRY; 1950 } 1951 1952 // We need to cast it to long because the value returned from RIL is a 32-bit integer, 1953 // but the time values used in AlarmManager are all 64-bit long. 1954 return (long) response.suggestedRetryTime; 1955 } 1956 1957 /** 1958 * @return the string for msg.what as our info. 1959 */ 1960 @Override 1961 protected String getWhatToString(int what) { 1962 return cmdToString(what); 1963 } 1964 1965 private static String msgToString(Message msg) { 1966 String retVal; 1967 if (msg == null) { 1968 retVal = "null"; 1969 } else { 1970 StringBuilder b = new StringBuilder(); 1971 1972 b.append("{what="); 1973 b.append(cmdToString(msg.what)); 1974 1975 b.append(" when="); 1976 TimeUtils.formatDuration(msg.getWhen() - SystemClock.uptimeMillis(), b); 1977 1978 if (msg.arg1 != 0) { 1979 b.append(" arg1="); 1980 b.append(msg.arg1); 1981 } 1982 1983 if (msg.arg2 != 0) { 1984 b.append(" arg2="); 1985 b.append(msg.arg2); 1986 } 1987 1988 if (msg.obj != null) { 1989 b.append(" obj="); 1990 b.append(msg.obj); 1991 } 1992 1993 b.append(" target="); 1994 b.append(msg.getTarget()); 1995 1996 b.append(" replyTo="); 1997 b.append(msg.replyTo); 1998 1999 b.append("}"); 2000 2001 retVal = b.toString(); 2002 } 2003 return retVal; 2004 } 2005 2006 static void slog(String s) { 2007 Rlog.d("DC", s); 2008 } 2009 2010 /** 2011 * Log with debug 2012 * 2013 * @param s is string log 2014 */ 2015 @Override 2016 protected void log(String s) { 2017 Rlog.d(getName(), s); 2018 } 2019 2020 /** 2021 * Log with debug attribute 2022 * 2023 * @param s is string log 2024 */ 2025 @Override 2026 protected void logd(String s) { 2027 Rlog.d(getName(), s); 2028 } 2029 2030 /** 2031 * Log with verbose attribute 2032 * 2033 * @param s is string log 2034 */ 2035 @Override 2036 protected void logv(String s) { 2037 Rlog.v(getName(), s); 2038 } 2039 2040 /** 2041 * Log with info attribute 2042 * 2043 * @param s is string log 2044 */ 2045 @Override 2046 protected void logi(String s) { 2047 Rlog.i(getName(), s); 2048 } 2049 2050 /** 2051 * Log with warning attribute 2052 * 2053 * @param s is string log 2054 */ 2055 @Override 2056 protected void logw(String s) { 2057 Rlog.w(getName(), s); 2058 } 2059 2060 /** 2061 * Log with error attribute 2062 * 2063 * @param s is string log 2064 */ 2065 @Override 2066 protected void loge(String s) { 2067 Rlog.e(getName(), s); 2068 } 2069 2070 /** 2071 * Log with error attribute 2072 * 2073 * @param s is string log 2074 * @param e is a Throwable which logs additional information. 2075 */ 2076 @Override 2077 protected void loge(String s, Throwable e) { 2078 Rlog.e(getName(), s, e); 2079 } 2080 2081 /** Doesn't print mApnList of ApnContext's which would be recursive */ 2082 public String toStringSimple() { 2083 return getName() + ": State=" + getCurrentState().getName() 2084 + " mApnSetting=" + mApnSetting + " RefCount=" + mApnContexts.size() 2085 + " mCid=" + mCid + " mCreateTime=" + mCreateTime 2086 + " mLastastFailTime=" + mLastFailTime 2087 + " mLastFailCause=" + mLastFailCause 2088 + " mTag=" + mTag 2089 + " mLinkProperties=" + mLinkProperties 2090 + " linkCapabilities=" + makeNetworkCapabilities() 2091 + " mRestrictedNetworkOverride=" + mRestrictedNetworkOverride; 2092 } 2093 2094 @Override 2095 public String toString() { 2096 return "{" + toStringSimple() + " mApnContexts=" + mApnContexts + "}"; 2097 } 2098 2099 private void dumpToLog() { 2100 dump(null, new PrintWriter(new StringWriter(0)) { 2101 @Override 2102 public void println(String s) { 2103 DataConnection.this.logd(s); 2104 } 2105 2106 @Override 2107 public void flush() { 2108 } 2109 }, null); 2110 } 2111 2112 /** 2113 * Dump the current state. 2114 * 2115 * @param fd 2116 * @param pw 2117 * @param args 2118 */ 2119 @Override 2120 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2121 pw.print("DataConnection "); 2122 super.dump(fd, pw, args); 2123 pw.println(" mApnContexts.size=" + mApnContexts.size()); 2124 pw.println(" mApnContexts=" + mApnContexts); 2125 pw.flush(); 2126 pw.println(" mDataConnectionTracker=" + mDct); 2127 pw.println(" mApnSetting=" + mApnSetting); 2128 pw.println(" mTag=" + mTag); 2129 pw.println(" mCid=" + mCid); 2130 pw.println(" mConnectionParams=" + mConnectionParams); 2131 pw.println(" mDisconnectParams=" + mDisconnectParams); 2132 pw.println(" mDcFailCause=" + mDcFailCause); 2133 pw.flush(); 2134 pw.println(" mPhone=" + mPhone); 2135 pw.flush(); 2136 pw.println(" mLinkProperties=" + mLinkProperties); 2137 pw.flush(); 2138 pw.println(" mDataRegState=" + mDataRegState); 2139 pw.println(" mRilRat=" + mRilRat); 2140 pw.println(" mNetworkCapabilities=" + makeNetworkCapabilities()); 2141 pw.println(" mCreateTime=" + TimeUtils.logTimeOfDay(mCreateTime)); 2142 pw.println(" mLastFailTime=" + TimeUtils.logTimeOfDay(mLastFailTime)); 2143 pw.println(" mLastFailCause=" + mLastFailCause); 2144 pw.flush(); 2145 pw.println(" mUserData=" + mUserData); 2146 pw.println(" mInstanceNumber=" + mInstanceNumber); 2147 pw.println(" mAc=" + mAc); 2148 pw.flush(); 2149 } 2150} 2151 2152