1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony.dataconnection; 18 19 import com.android.internal.telephony.CallTracker; 20 import com.android.internal.telephony.CarrierSignalAgent; 21 import com.android.internal.telephony.CommandException; 22 import com.android.internal.telephony.DctConstants; 23 import com.android.internal.telephony.Phone; 24 import com.android.internal.telephony.PhoneConstants; 25 import com.android.internal.telephony.RILConstants; 26 import com.android.internal.telephony.RetryManager; 27 import com.android.internal.telephony.ServiceStateTracker; 28 import com.android.internal.util.AsyncChannel; 29 import com.android.internal.util.Protocol; 30 import com.android.internal.util.State; 31 import com.android.internal.util.StateMachine; 32 33 import android.app.PendingIntent; 34 import android.content.Context; 35 import android.net.ConnectivityManager; 36 import android.net.LinkProperties; 37 import android.net.NetworkAgent; 38 import android.net.NetworkCapabilities; 39 import android.net.NetworkInfo; 40 import android.net.NetworkMisc; 41 import android.net.ProxyInfo; 42 import android.os.AsyncResult; 43 import android.os.Looper; 44 import android.os.Message; 45 import android.os.SystemClock; 46 import android.os.SystemProperties; 47 import android.telephony.Rlog; 48 import android.telephony.ServiceState; 49 import android.telephony.TelephonyManager; 50 import android.text.TextUtils; 51 import android.util.Pair; 52 import android.util.Patterns; 53 import android.util.TimeUtils; 54 55 import java.io.FileDescriptor; 56 import java.io.PrintWriter; 57 import java.io.StringWriter; 58 import java.util.ArrayList; 59 import java.util.Locale; 60 import java.util.concurrent.atomic.AtomicInteger; 61 import java.net.InetAddress; 62 import java.util.Collection; 63 import 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 */ 77 public 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 ConnectionParams(ApnContext apnContext, int profileId, int rilRadioTechnology, Message onCompletedMsg, int connectionGeneration)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 toString()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 DisconnectParams(ApnContext apnContext, String reason, Message onCompletedMsg)135 DisconnectParams(ApnContext apnContext, String reason, Message onCompletedMsg) { 136 mApnContext = apnContext; 137 mReason = reason; 138 mOnCompletedMsg = onCompletedMsg; 139 } 140 141 @Override toString()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 cmdToString(int cmd)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 */ makeDataConnection(Phone phone, int id, DcTracker dct, DcTesterFailBringUpAll failBringUpAll, DcController dcc)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 dispose()249 void dispose() { 250 log("dispose: call quiteNow()"); 251 quitNow(); 252 } 253 254 /* Getter functions */ 255 getCopyNetworkCapabilities()256 NetworkCapabilities getCopyNetworkCapabilities() { 257 return makeNetworkCapabilities(); 258 } 259 getCopyLinkProperties()260 LinkProperties getCopyLinkProperties() { 261 return new LinkProperties(mLinkProperties); 262 } 263 getIsInactive()264 boolean getIsInactive() { 265 return getCurrentState() == mInactiveState; 266 } 267 getCid()268 int getCid() { 269 return mCid; 270 } 271 getApnSetting()272 ApnSetting getApnSetting() { 273 return mApnSetting; 274 } 275 setLinkPropertiesHttpProxy(ProxyInfo proxy)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; UpdateLinkPropertyResult(LinkProperties curLp)284 public UpdateLinkPropertyResult(LinkProperties curLp) { 285 oldLp = curLp; 286 newLp = curLp; 287 } 288 } 289 isIpv4Connected()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 isIpv6Connected()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 updateLinkProperty(DataCallResponse newState)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 */ checkSetMtu(ApnSetting apn, LinkProperties lp)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) DataConnection(Phone phone, String name, int id, DcTracker dct, DcTesterFailBringUpAll failBringUpAll, DcController dcc)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 */ onConnect(ConnectionParams cp)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 */ tearDownData(Object o)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 notifyAllWithEvent(ApnContext alreadySent, int event, String reason)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 notifyAllOfConnected(String reason)548 private void notifyAllOfConnected(String reason) { 549 notifyAllWithEvent(null, DctConstants.EVENT_DATA_SETUP_COMPLETE, reason); 550 } 551 notifyAllOfDisconnectDcRetrying(String reason)552 private void notifyAllOfDisconnectDcRetrying(String reason) { 553 notifyAllWithEvent(null, DctConstants.EVENT_DISCONNECT_DC_RETRYING, reason); 554 } notifyAllDisconnectCompleted(DcFailCause cause)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 */ notifyConnectCompleted(ConnectionParams cp, DcFailCause cause, boolean sendAll)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 */ notifyDisconnectCompleted(DisconnectParams dp, boolean sendAll)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 */ getDataConnectionId()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 */ clearSettings()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 */ onSetupConnectionCompleted(AsyncResult ar)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 isDnsOk(String[] domainNameServers)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 updateTcpBufferSizes(int rilRat)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 setNetworkRestriction()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 makeNetworkCapabilities()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 isIpAddress(String address)996 private boolean isIpAddress(String address) { 997 if (address == null) return false; 998 999 return Patterns.IP_ADDRESS.matcher(address).matches(); 1000 } 1001 setLinkProperties(DataCallResponse response, LinkProperties lp)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 */ initConnection(ConnectionParams cp)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 enter()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 exit()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 processMessage(Message msg)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 updateNetworkInfoSuspendState()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 setEnterNotificationParams(ConnectionParams cp, DcFailCause cause)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 setEnterNotificationParams(DisconnectParams dp)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 setEnterNotificationParams(DcFailCause cause)1310 public void setEnterNotificationParams(DcFailCause cause) { 1311 mConnectionParams = null; 1312 mDisconnectParams = null; 1313 mDcFailCause = cause; 1314 } 1315 1316 @Override enter()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 exit()1350 public void exit() { 1351 } 1352 1353 @Override processMessage(Message msg)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 processMessage(Message msg)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 { enter()1556 @Override public void enter() { 1557 if (DBG) log("DcActiveState: enter dc=" + DataConnection.this); 1558 1559 boolean createNetworkAgent = true; 1560 // If a disconnect is already pending, avoid notifying all of connected 1561 if (hasMessages(EVENT_DISCONNECT) || 1562 hasMessages(EVENT_DISCONNECT_ALL) || 1563 hasDeferredMessages(EVENT_DISCONNECT) || 1564 hasDeferredMessages(EVENT_DISCONNECT_ALL)) { 1565 log("DcActiveState: skipping notifyAllOfConnected()"); 1566 createNetworkAgent = false; 1567 } else { 1568 // If we were retrying there maybe more than one, otherwise they'll only be one. 1569 notifyAllOfConnected(Phone.REASON_CONNECTED); 1570 } 1571 1572 mPhone.getCallTracker().registerForVoiceCallStarted(getHandler(), 1573 DataConnection.EVENT_DATA_CONNECTION_VOICE_CALL_STARTED, null); 1574 mPhone.getCallTracker().registerForVoiceCallEnded(getHandler(), 1575 DataConnection.EVENT_DATA_CONNECTION_VOICE_CALL_ENDED, null); 1576 1577 // If the EVENT_CONNECT set the current max retry restore it here 1578 // if it didn't then this is effectively a NOP. 1579 mDcController.addActiveDcByCid(DataConnection.this); 1580 1581 mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, 1582 mNetworkInfo.getReason(), null); 1583 mNetworkInfo.setExtraInfo(mApnSetting.apn); 1584 updateTcpBufferSizes(mRilRat); 1585 1586 final NetworkMisc misc = new NetworkMisc(); 1587 final CarrierSignalAgent carrierSignalAgent = mPhone.getCarrierSignalAgent(); 1588 if(carrierSignalAgent.hasRegisteredCarrierSignalReceivers()) { 1589 // carrierSignal Receivers will place the carrier-specific provisioning notification 1590 misc.provisioningNotificationDisabled = true; 1591 } 1592 misc.subscriberId = mPhone.getSubscriberId(); 1593 1594 if (createNetworkAgent) { 1595 setNetworkRestriction(); 1596 mNetworkAgent = new DcNetworkAgent(getHandler().getLooper(), mPhone.getContext(), 1597 "DcNetworkAgent", mNetworkInfo, makeNetworkCapabilities(), mLinkProperties, 1598 50, misc); 1599 } 1600 } 1601 1602 @Override exit()1603 public void exit() { 1604 if (DBG) log("DcActiveState: exit dc=" + this); 1605 String reason = mNetworkInfo.getReason(); 1606 if(mDcController.isExecutingCarrierChange()) { 1607 reason = Phone.REASON_CARRIER_CHANGE; 1608 } else if (mDisconnectParams != null && mDisconnectParams.mReason != null) { 1609 reason = mDisconnectParams.mReason; 1610 } else if (mDcFailCause != null) { 1611 reason = mDcFailCause.toString(); 1612 } 1613 mPhone.getCallTracker().unregisterForVoiceCallStarted(getHandler()); 1614 mPhone.getCallTracker().unregisterForVoiceCallEnded(getHandler()); 1615 1616 mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, 1617 reason, mNetworkInfo.getExtraInfo()); 1618 if (mNetworkAgent != null) { 1619 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 1620 mNetworkAgent = null; 1621 } 1622 } 1623 1624 @Override processMessage(Message msg)1625 public boolean processMessage(Message msg) { 1626 boolean retVal; 1627 1628 switch (msg.what) { 1629 case EVENT_CONNECT: { 1630 ConnectionParams cp = (ConnectionParams) msg.obj; 1631 // either add this new apn context to our set or 1632 // update the existing cp with the latest connection generation number 1633 mApnContexts.put(cp.mApnContext, cp); 1634 if (DBG) { 1635 log("DcActiveState: EVENT_CONNECT cp=" + cp + " dc=" + DataConnection.this); 1636 } 1637 notifyConnectCompleted(cp, DcFailCause.NONE, false); 1638 retVal = HANDLED; 1639 break; 1640 } 1641 case EVENT_DISCONNECT: { 1642 DisconnectParams dp = (DisconnectParams) msg.obj; 1643 if (DBG) { 1644 log("DcActiveState: EVENT_DISCONNECT dp=" + dp 1645 + " dc=" + DataConnection.this); 1646 } 1647 if (mApnContexts.containsKey(dp.mApnContext)) { 1648 if (DBG) { 1649 log("DcActiveState msg.what=EVENT_DISCONNECT RefCount=" 1650 + mApnContexts.size()); 1651 } 1652 1653 if (mApnContexts.size() == 1) { 1654 mApnContexts.clear(); 1655 mDisconnectParams = dp; 1656 mConnectionParams = null; 1657 dp.mTag = mTag; 1658 tearDownData(dp); 1659 transitionTo(mDisconnectingState); 1660 } else { 1661 mApnContexts.remove(dp.mApnContext); 1662 notifyDisconnectCompleted(dp, false); 1663 } 1664 } else { 1665 log("DcActiveState ERROR no such apnContext=" + dp.mApnContext 1666 + " in this dc=" + DataConnection.this); 1667 notifyDisconnectCompleted(dp, false); 1668 } 1669 retVal = HANDLED; 1670 break; 1671 } 1672 case EVENT_DISCONNECT_ALL: { 1673 if (DBG) { 1674 log("DcActiveState EVENT_DISCONNECT clearing apn contexts," 1675 + " dc=" + DataConnection.this); 1676 } 1677 DisconnectParams dp = (DisconnectParams) msg.obj; 1678 mDisconnectParams = dp; 1679 mConnectionParams = null; 1680 dp.mTag = mTag; 1681 tearDownData(dp); 1682 transitionTo(mDisconnectingState); 1683 retVal = HANDLED; 1684 break; 1685 } 1686 case EVENT_LOST_CONNECTION: { 1687 if (DBG) { 1688 log("DcActiveState EVENT_LOST_CONNECTION dc=" + DataConnection.this); 1689 } 1690 1691 mInactiveState.setEnterNotificationParams(DcFailCause.LOST_CONNECTION); 1692 transitionTo(mInactiveState); 1693 retVal = HANDLED; 1694 break; 1695 } 1696 case EVENT_DATA_CONNECTION_ROAM_ON: { 1697 mNetworkInfo.setRoaming(true); 1698 if (mNetworkAgent != null) { 1699 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 1700 } 1701 retVal = HANDLED; 1702 break; 1703 } 1704 case EVENT_DATA_CONNECTION_ROAM_OFF: { 1705 mNetworkInfo.setRoaming(false); 1706 if (mNetworkAgent != null) { 1707 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 1708 } 1709 retVal = HANDLED; 1710 break; 1711 } 1712 case EVENT_BW_REFRESH_RESPONSE: { 1713 AsyncResult ar = (AsyncResult)msg.obj; 1714 if (ar.exception != null) { 1715 log("EVENT_BW_REFRESH_RESPONSE: error ignoring, e=" + ar.exception); 1716 } else { 1717 final ArrayList<Integer> capInfo = (ArrayList<Integer>)ar.result; 1718 final int lceBwDownKbps = capInfo.get(0); 1719 NetworkCapabilities nc = makeNetworkCapabilities(); 1720 if (mPhone.getLceStatus() == RILConstants.LCE_ACTIVE) { 1721 nc.setLinkDownstreamBandwidthKbps(lceBwDownKbps); 1722 if (mNetworkAgent != null) { 1723 mNetworkAgent.sendNetworkCapabilities(nc); 1724 } 1725 } 1726 } 1727 retVal = HANDLED; 1728 break; 1729 } 1730 case EVENT_DATA_CONNECTION_VOICE_CALL_STARTED: 1731 case EVENT_DATA_CONNECTION_VOICE_CALL_ENDED: { 1732 if (updateNetworkInfoSuspendState() && mNetworkAgent != null) { 1733 // state changed 1734 mNetworkAgent.sendNetworkInfo(mNetworkInfo); 1735 } 1736 retVal = HANDLED; 1737 break; 1738 } 1739 default: 1740 if (VDBG) { 1741 log("DcActiveState not handled msg.what=" + getWhatToString(msg.what)); 1742 } 1743 retVal = NOT_HANDLED; 1744 break; 1745 } 1746 return retVal; 1747 } 1748 } 1749 private DcActiveState mActiveState = new DcActiveState(); 1750 1751 /** 1752 * The state machine is disconnecting. 1753 */ 1754 private class DcDisconnectingState extends State { 1755 @Override processMessage(Message msg)1756 public boolean processMessage(Message msg) { 1757 boolean retVal; 1758 1759 switch (msg.what) { 1760 case EVENT_CONNECT: 1761 if (DBG) log("DcDisconnectingState msg.what=EVENT_CONNECT. Defer. RefCount = " 1762 + mApnContexts.size()); 1763 deferMessage(msg); 1764 retVal = HANDLED; 1765 break; 1766 1767 case EVENT_DEACTIVATE_DONE: 1768 AsyncResult ar = (AsyncResult) msg.obj; 1769 DisconnectParams dp = (DisconnectParams) ar.userObj; 1770 1771 String str = "DcDisconnectingState msg.what=EVENT_DEACTIVATE_DONE RefCount=" 1772 + mApnContexts.size(); 1773 if (DBG) log(str); 1774 if (dp.mApnContext != null) dp.mApnContext.requestLog(str); 1775 1776 if (dp.mTag == mTag) { 1777 // Transition to inactive but send notifications after 1778 // we've entered the mInactive state. 1779 mInactiveState.setEnterNotificationParams((DisconnectParams) ar.userObj); 1780 transitionTo(mInactiveState); 1781 } else { 1782 if (DBG) log("DcDisconnectState stale EVENT_DEACTIVATE_DONE" 1783 + " dp.tag=" + dp.mTag + " mTag=" + mTag); 1784 } 1785 retVal = HANDLED; 1786 break; 1787 1788 default: 1789 if (VDBG) { 1790 log("DcDisconnectingState not handled msg.what=" 1791 + getWhatToString(msg.what)); 1792 } 1793 retVal = NOT_HANDLED; 1794 break; 1795 } 1796 return retVal; 1797 } 1798 } 1799 private DcDisconnectingState mDisconnectingState = new DcDisconnectingState(); 1800 1801 /** 1802 * The state machine is disconnecting after an creating a connection. 1803 */ 1804 private class DcDisconnectionErrorCreatingConnection extends State { 1805 @Override processMessage(Message msg)1806 public boolean processMessage(Message msg) { 1807 boolean retVal; 1808 1809 switch (msg.what) { 1810 case EVENT_DEACTIVATE_DONE: 1811 AsyncResult ar = (AsyncResult) msg.obj; 1812 ConnectionParams cp = (ConnectionParams) ar.userObj; 1813 if (cp.mTag == mTag) { 1814 String str = "DcDisconnectionErrorCreatingConnection" + 1815 " msg.what=EVENT_DEACTIVATE_DONE"; 1816 if (DBG) log(str); 1817 if (cp.mApnContext != null) cp.mApnContext.requestLog(str); 1818 1819 // Transition to inactive but send notifications after 1820 // we've entered the mInactive state. 1821 mInactiveState.setEnterNotificationParams(cp, 1822 DcFailCause.UNACCEPTABLE_NETWORK_PARAMETER); 1823 transitionTo(mInactiveState); 1824 } else { 1825 if (DBG) { 1826 log("DcDisconnectionErrorCreatingConnection stale EVENT_DEACTIVATE_DONE" 1827 + " dp.tag=" + cp.mTag + ", mTag=" + mTag); 1828 } 1829 } 1830 retVal = HANDLED; 1831 break; 1832 1833 default: 1834 if (VDBG) { 1835 log("DcDisconnectionErrorCreatingConnection not handled msg.what=" 1836 + getWhatToString(msg.what)); 1837 } 1838 retVal = NOT_HANDLED; 1839 break; 1840 } 1841 return retVal; 1842 } 1843 } 1844 private DcDisconnectionErrorCreatingConnection mDisconnectingErrorCreatingConnection = 1845 new DcDisconnectionErrorCreatingConnection(); 1846 1847 1848 private class DcNetworkAgent extends NetworkAgent { DcNetworkAgent(Looper l, Context c, String TAG, NetworkInfo ni, NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc)1849 public DcNetworkAgent(Looper l, Context c, String TAG, NetworkInfo ni, 1850 NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) { 1851 super(l, c, TAG, ni, nc, lp, score, misc); 1852 } 1853 1854 @Override unwanted()1855 protected void unwanted() { 1856 if (mNetworkAgent != this) { 1857 log("DcNetworkAgent: unwanted found mNetworkAgent=" + mNetworkAgent + 1858 ", which isn't me. Aborting unwanted"); 1859 return; 1860 } 1861 // this can only happen if our exit has been called - we're already disconnected 1862 if (mApnContexts == null) return; 1863 for (ConnectionParams cp : mApnContexts.values()) { 1864 final ApnContext apnContext = cp.mApnContext; 1865 final Pair<ApnContext, Integer> pair = 1866 new Pair<ApnContext, Integer>(apnContext, cp.mConnectionGeneration); 1867 log("DcNetworkAgent: [unwanted]: disconnect apnContext=" + apnContext); 1868 Message msg = mDct.obtainMessage(DctConstants.EVENT_DISCONNECT_DONE, pair); 1869 DisconnectParams dp = new DisconnectParams(apnContext, apnContext.getReason(), msg); 1870 DataConnection.this.sendMessage(DataConnection.this. 1871 obtainMessage(EVENT_DISCONNECT, dp)); 1872 } 1873 } 1874 1875 @Override pollLceData()1876 protected void pollLceData() { 1877 if(mPhone.getLceStatus() == RILConstants.LCE_ACTIVE) { // active LCE service 1878 mPhone.mCi.pullLceData(DataConnection.this.obtainMessage(EVENT_BW_REFRESH_RESPONSE)); 1879 } 1880 } 1881 1882 @Override networkStatus(int status, String redirectUrl)1883 protected void networkStatus(int status, String redirectUrl) { 1884 if(!TextUtils.isEmpty(redirectUrl)) { 1885 log("validation status: " + status + " with redirection URL: " + redirectUrl); 1886 /* its possible that we have multiple DataConnection with INTERNET_CAPABILITY 1887 all fail the validation with the same redirection url, send CMD back to DCTracker 1888 and let DcTracker to make the decision */ 1889 Message msg = mDct.obtainMessage(DctConstants.EVENT_REDIRECTION_DETECTED, 1890 redirectUrl); 1891 msg.sendToTarget(); 1892 } 1893 } 1894 } 1895 1896 // ******* "public" interface 1897 1898 /** 1899 * Used for testing purposes. 1900 */ tearDownNow()1901 /* package */ void tearDownNow() { 1902 if (DBG) log("tearDownNow()"); 1903 sendMessage(obtainMessage(EVENT_TEAR_DOWN_NOW)); 1904 } 1905 1906 /** 1907 * Using the result of the SETUP_DATA_CALL determine the retry delay. 1908 * 1909 * @param ar is the result from SETUP_DATA_CALL 1910 * @return NO_SUGGESTED_RETRY_DELAY if no retry is needed otherwise the delay to the 1911 * next SETUP_DATA_CALL 1912 */ getSuggestedRetryDelay(AsyncResult ar)1913 private long getSuggestedRetryDelay(AsyncResult ar) { 1914 1915 DataCallResponse response = (DataCallResponse) ar.result; 1916 1917 /** According to ril.h 1918 * The value < 0 means no value is suggested 1919 * The value 0 means retry should be done ASAP. 1920 * The value of Integer.MAX_VALUE(0x7fffffff) means no retry. 1921 */ 1922 1923 // The value < 0 means no value is suggested 1924 if (response.suggestedRetryTime < 0) { 1925 if (DBG) log("No suggested retry delay."); 1926 return RetryManager.NO_SUGGESTED_RETRY_DELAY; 1927 } 1928 // The value of Integer.MAX_VALUE(0x7fffffff) means no retry. 1929 else if (response.suggestedRetryTime == Integer.MAX_VALUE) { 1930 if (DBG) log("Modem suggested not retrying."); 1931 return RetryManager.NO_RETRY; 1932 } 1933 1934 // We need to cast it to long because the value returned from RIL is a 32-bit integer, 1935 // but the time values used in AlarmManager are all 64-bit long. 1936 return (long) response.suggestedRetryTime; 1937 } 1938 1939 /** 1940 * @return the string for msg.what as our info. 1941 */ 1942 @Override getWhatToString(int what)1943 protected String getWhatToString(int what) { 1944 return cmdToString(what); 1945 } 1946 msgToString(Message msg)1947 private static String msgToString(Message msg) { 1948 String retVal; 1949 if (msg == null) { 1950 retVal = "null"; 1951 } else { 1952 StringBuilder b = new StringBuilder(); 1953 1954 b.append("{what="); 1955 b.append(cmdToString(msg.what)); 1956 1957 b.append(" when="); 1958 TimeUtils.formatDuration(msg.getWhen() - SystemClock.uptimeMillis(), b); 1959 1960 if (msg.arg1 != 0) { 1961 b.append(" arg1="); 1962 b.append(msg.arg1); 1963 } 1964 1965 if (msg.arg2 != 0) { 1966 b.append(" arg2="); 1967 b.append(msg.arg2); 1968 } 1969 1970 if (msg.obj != null) { 1971 b.append(" obj="); 1972 b.append(msg.obj); 1973 } 1974 1975 b.append(" target="); 1976 b.append(msg.getTarget()); 1977 1978 b.append(" replyTo="); 1979 b.append(msg.replyTo); 1980 1981 b.append("}"); 1982 1983 retVal = b.toString(); 1984 } 1985 return retVal; 1986 } 1987 slog(String s)1988 static void slog(String s) { 1989 Rlog.d("DC", s); 1990 } 1991 1992 /** 1993 * Log with debug 1994 * 1995 * @param s is string log 1996 */ 1997 @Override log(String s)1998 protected void log(String s) { 1999 Rlog.d(getName(), s); 2000 } 2001 2002 /** 2003 * Log with debug attribute 2004 * 2005 * @param s is string log 2006 */ 2007 @Override logd(String s)2008 protected void logd(String s) { 2009 Rlog.d(getName(), s); 2010 } 2011 2012 /** 2013 * Log with verbose attribute 2014 * 2015 * @param s is string log 2016 */ 2017 @Override logv(String s)2018 protected void logv(String s) { 2019 Rlog.v(getName(), s); 2020 } 2021 2022 /** 2023 * Log with info attribute 2024 * 2025 * @param s is string log 2026 */ 2027 @Override logi(String s)2028 protected void logi(String s) { 2029 Rlog.i(getName(), s); 2030 } 2031 2032 /** 2033 * Log with warning attribute 2034 * 2035 * @param s is string log 2036 */ 2037 @Override logw(String s)2038 protected void logw(String s) { 2039 Rlog.w(getName(), s); 2040 } 2041 2042 /** 2043 * Log with error attribute 2044 * 2045 * @param s is string log 2046 */ 2047 @Override loge(String s)2048 protected void loge(String s) { 2049 Rlog.e(getName(), s); 2050 } 2051 2052 /** 2053 * Log with error attribute 2054 * 2055 * @param s is string log 2056 * @param e is a Throwable which logs additional information. 2057 */ 2058 @Override loge(String s, Throwable e)2059 protected void loge(String s, Throwable e) { 2060 Rlog.e(getName(), s, e); 2061 } 2062 2063 /** Doesn't print mApnList of ApnContext's which would be recursive */ toStringSimple()2064 public String toStringSimple() { 2065 return getName() + ": State=" + getCurrentState().getName() 2066 + " mApnSetting=" + mApnSetting + " RefCount=" + mApnContexts.size() 2067 + " mCid=" + mCid + " mCreateTime=" + mCreateTime 2068 + " mLastastFailTime=" + mLastFailTime 2069 + " mLastFailCause=" + mLastFailCause 2070 + " mTag=" + mTag 2071 + " mLinkProperties=" + mLinkProperties 2072 + " linkCapabilities=" + makeNetworkCapabilities() 2073 + " mRestrictedNetworkOverride=" + mRestrictedNetworkOverride; 2074 } 2075 2076 @Override toString()2077 public String toString() { 2078 return "{" + toStringSimple() + " mApnContexts=" + mApnContexts + "}"; 2079 } 2080 dumpToLog()2081 private void dumpToLog() { 2082 dump(null, new PrintWriter(new StringWriter(0)) { 2083 @Override 2084 public void println(String s) { 2085 DataConnection.this.logd(s); 2086 } 2087 2088 @Override 2089 public void flush() { 2090 } 2091 }, null); 2092 } 2093 2094 /** 2095 * Dump the current state. 2096 * 2097 * @param fd 2098 * @param pw 2099 * @param args 2100 */ 2101 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)2102 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2103 pw.print("DataConnection "); 2104 super.dump(fd, pw, args); 2105 pw.println(" mApnContexts.size=" + mApnContexts.size()); 2106 pw.println(" mApnContexts=" + mApnContexts); 2107 pw.flush(); 2108 pw.println(" mDataConnectionTracker=" + mDct); 2109 pw.println(" mApnSetting=" + mApnSetting); 2110 pw.println(" mTag=" + mTag); 2111 pw.println(" mCid=" + mCid); 2112 pw.println(" mConnectionParams=" + mConnectionParams); 2113 pw.println(" mDisconnectParams=" + mDisconnectParams); 2114 pw.println(" mDcFailCause=" + mDcFailCause); 2115 pw.flush(); 2116 pw.println(" mPhone=" + mPhone); 2117 pw.flush(); 2118 pw.println(" mLinkProperties=" + mLinkProperties); 2119 pw.flush(); 2120 pw.println(" mDataRegState=" + mDataRegState); 2121 pw.println(" mRilRat=" + mRilRat); 2122 pw.println(" mNetworkCapabilities=" + makeNetworkCapabilities()); 2123 pw.println(" mCreateTime=" + TimeUtils.logTimeOfDay(mCreateTime)); 2124 pw.println(" mLastFailTime=" + TimeUtils.logTimeOfDay(mLastFailTime)); 2125 pw.println(" mLastFailCause=" + mLastFailCause); 2126 pw.flush(); 2127 pw.println(" mUserData=" + mUserData); 2128 pw.println(" mInstanceNumber=" + mInstanceNumber); 2129 pw.println(" mAc=" + mAc); 2130 pw.flush(); 2131 } 2132 } 2133 2134