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