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 android.app.PendingIntent; 20 import android.net.ConnectivityManager; 21 import android.net.NetworkCapabilities; 22 import android.net.NetworkConfig; 23 import android.net.NetworkRequest; 24 import android.telephony.Rlog; 25 import android.text.TextUtils; 26 import android.util.LocalLog; 27 import android.util.SparseIntArray; 28 29 import com.android.internal.R; 30 import com.android.internal.telephony.DctConstants; 31 import com.android.internal.telephony.Phone; 32 import com.android.internal.telephony.PhoneConstants; 33 import com.android.internal.telephony.RetryManager; 34 import com.android.internal.util.IndentingPrintWriter; 35 36 import java.io.FileDescriptor; 37 import java.io.PrintWriter; 38 import java.util.ArrayList; 39 import java.util.List; 40 import java.util.concurrent.atomic.AtomicBoolean; 41 import java.util.concurrent.atomic.AtomicInteger; 42 43 /** 44 * Maintain the Apn context 45 */ 46 public class ApnContext { 47 48 public final String LOG_TAG; 49 private final static String SLOG_TAG = "ApnContext"; 50 51 protected static final boolean DBG = false; 52 53 private final Phone mPhone; 54 55 private final String mApnType; 56 57 private DctConstants.State mState; 58 59 public final int priority; 60 61 private ApnSetting mApnSetting; 62 63 DcAsyncChannel mDcAc; 64 65 String mReason; 66 67 PendingIntent mReconnectAlarmIntent; 68 69 /** 70 * user/app requested connection on this APN 71 */ 72 AtomicBoolean mDataEnabled; 73 74 private final Object mRefCountLock = new Object(); 75 private int mRefCount = 0; 76 77 /** 78 * carrier requirements met 79 */ 80 AtomicBoolean mDependencyMet; 81 82 private final DcTracker mDcTracker; 83 84 /** 85 * Remember this as a change in this value to a more permissive state 86 * should cause us to retry even permanent failures 87 */ 88 private boolean mConcurrentVoiceAndDataAllowed; 89 90 /** 91 * used to track a single connection request so disconnects can get ignored if 92 * obsolete. 93 */ 94 private final AtomicInteger mConnectionGeneration = new AtomicInteger(0); 95 96 /** 97 * Retry manager that handles the APN retry and delays. 98 */ 99 private final RetryManager mRetryManager; 100 101 /** 102 * AonContext constructor 103 * @param phone phone object 104 * @param apnType APN type (e.g. default, supl, mms, etc...) 105 * @param logTag Tag for logging 106 * @param config Network configuration 107 * @param tracker Data call tracker 108 */ 109 public ApnContext(Phone phone, String apnType, String logTag, NetworkConfig config, 110 DcTracker tracker) { 111 mPhone = phone; 112 mApnType = apnType; 113 mState = DctConstants.State.IDLE; 114 setReason(Phone.REASON_DATA_ENABLED); 115 mDataEnabled = new AtomicBoolean(false); 116 mDependencyMet = new AtomicBoolean(config.dependencyMet); 117 priority = config.priority; 118 LOG_TAG = logTag; 119 mDcTracker = tracker; 120 mRetryManager = new RetryManager(phone, apnType); 121 } 122 123 /** 124 * Get the APN type 125 * @return The APN type 126 */ 127 public String getApnType() { 128 return mApnType; 129 } 130 131 /** 132 * Get the data call async channel. 133 * @return The data call async channel 134 */ 135 public synchronized DcAsyncChannel getDcAc() { 136 return mDcAc; 137 } 138 139 /** 140 * Set the data call async channel. 141 * @param dcac The data call async channel 142 */ 143 public synchronized void setDataConnectionAc(DcAsyncChannel dcac) { 144 if (DBG) { 145 log("setDataConnectionAc: old dcac=" + mDcAc + " new dcac=" + dcac 146 + " this=" + this); 147 } 148 mDcAc = dcac; 149 } 150 151 /** 152 * Release data connection. 153 * @param reason The reason of releasing data connection 154 */ 155 public synchronized void releaseDataConnection(String reason) { 156 if (mDcAc != null) { 157 mDcAc.tearDown(this, reason, null); 158 mDcAc = null; 159 } 160 setState(DctConstants.State.IDLE); 161 } 162 163 /** 164 * Get the reconnect intent. 165 * @return The reconnect intent 166 */ 167 public synchronized PendingIntent getReconnectIntent() { 168 return mReconnectAlarmIntent; 169 } 170 171 /** 172 * Save the reconnect intent which can be used for cancelling later. 173 * @param intent The reconnect intent 174 */ 175 public synchronized void setReconnectIntent(PendingIntent intent) { 176 mReconnectAlarmIntent = intent; 177 } 178 179 /** 180 * Get the current APN setting. 181 * @return APN setting 182 */ 183 public synchronized ApnSetting getApnSetting() { 184 if (DBG) log("getApnSetting: apnSetting=" + mApnSetting); 185 return mApnSetting; 186 } 187 188 /** 189 * Set the APN setting. 190 * @param apnSetting APN setting 191 */ 192 public synchronized void setApnSetting(ApnSetting apnSetting) { 193 if (DBG) log("setApnSetting: apnSetting=" + apnSetting); 194 mApnSetting = apnSetting; 195 } 196 197 /** 198 * Set the list of APN candidates which will be used for data call setup later. 199 * @param waitingApns List of APN candidates 200 */ 201 public synchronized void setWaitingApns(ArrayList<ApnSetting> waitingApns) { 202 mRetryManager.setWaitingApns(waitingApns); 203 } 204 205 /** 206 * Get the next available APN to try. 207 * @return APN setting which will be used for data call setup. Return null if there is no 208 * APN can be retried. 209 */ 210 public ApnSetting getNextApnSetting() { 211 return mRetryManager.getNextApnSetting(); 212 } 213 214 /** 215 * Save the modem suggested delay for retrying the current APN. 216 * This method is called when we get the suggested delay from RIL. 217 * @param delay The delay in milliseconds 218 */ 219 public void setModemSuggestedDelay(long delay) { 220 mRetryManager.setModemSuggestedDelay(delay); 221 } 222 223 /** 224 * Get the delay for trying the next APN setting if the current one failed. 225 * @param failFastEnabled True if fail fast mode enabled. In this case we'll use a shorter 226 * delay. 227 * @return The delay in milliseconds 228 */ 229 public long getDelayForNextApn(boolean failFastEnabled) { 230 return mRetryManager.getDelayForNextApn(failFastEnabled || isFastRetryReason()); 231 } 232 233 /** 234 * Mark the current APN setting permanently failed, which means it will not be retried anymore. 235 * @param apn APN setting 236 */ 237 public void markApnPermanentFailed(ApnSetting apn) { 238 mRetryManager.markApnPermanentFailed(apn); 239 } 240 241 /** 242 * Get the list of waiting APNs. 243 * @return the list of waiting APNs 244 */ 245 public ArrayList<ApnSetting> getWaitingApns() { 246 return mRetryManager.getWaitingApns(); 247 } 248 249 /** 250 * Save the state indicating concurrent voice/data allowed. 251 * @param allowed True if concurrent voice/data is allowed 252 */ 253 public synchronized void setConcurrentVoiceAndDataAllowed(boolean allowed) { 254 mConcurrentVoiceAndDataAllowed = allowed; 255 } 256 257 /** 258 * Get the state indicating concurrent voice/data allowed. 259 * @return True if concurrent voice/data is allowed 260 */ 261 public synchronized boolean isConcurrentVoiceAndDataAllowed() { 262 return mConcurrentVoiceAndDataAllowed; 263 } 264 265 /** 266 * Set the current data call state. 267 * @param s Current data call state 268 */ 269 public synchronized void setState(DctConstants.State s) { 270 if (DBG) { 271 log("setState: " + s + ", previous state:" + mState); 272 } 273 274 if (mState != s) { 275 mStateLocalLog.log("State changed from " + mState + " to " + s); 276 mState = s; 277 } 278 279 if (mState == DctConstants.State.FAILED) { 280 if (mRetryManager.getWaitingApns() != null) { 281 mRetryManager.getWaitingApns().clear(); // when teardown the connection and set to IDLE 282 } 283 } 284 } 285 286 /** 287 * Get the current data call state. 288 * @return The current data call state 289 */ 290 public synchronized DctConstants.State getState() { 291 return mState; 292 } 293 294 /** 295 * Check whether the data call is disconnected or not. 296 * @return True if the data call is disconnected 297 */ 298 public boolean isDisconnected() { 299 DctConstants.State currentState = getState(); 300 return ((currentState == DctConstants.State.IDLE) || 301 currentState == DctConstants.State.FAILED); 302 } 303 304 /** 305 * Set the reason for data call connection. 306 * @param reason Reason for data call connection 307 */ 308 public synchronized void setReason(String reason) { 309 if (DBG) { 310 log("set reason as " + reason + ",current state " + mState); 311 } 312 mReason = reason; 313 } 314 315 /** 316 * Get the reason for data call connection. 317 * @return The reason for data call connection 318 */ 319 public synchronized String getReason() { 320 return mReason; 321 } 322 323 /** 324 * Check if ready for data call connection 325 * @return True if ready, otherwise false. 326 */ 327 public boolean isReady() { 328 return mDataEnabled.get() && mDependencyMet.get(); 329 } 330 331 /** 332 * Check if the data call is in the state which allow connecting. 333 * @return True if allowed, otherwise false. 334 */ 335 public boolean isConnectable() { 336 return isReady() && ((mState == DctConstants.State.IDLE) 337 || (mState == DctConstants.State.SCANNING) 338 || (mState == DctConstants.State.RETRYING) 339 || (mState == DctConstants.State.FAILED)); 340 } 341 342 /** 343 * Check if apn reason is fast retry reason which should apply shorter delay between apn re-try. 344 * @return True if it is fast retry reason, otherwise false. 345 */ 346 private boolean isFastRetryReason() { 347 return Phone.REASON_NW_TYPE_CHANGED.equals(mReason) || 348 Phone.REASON_APN_CHANGED.equals(mReason); 349 } 350 351 /** Check if the data call is in connected or connecting state. 352 * @return True if the data call is in connected or connecting state 353 */ 354 public boolean isConnectedOrConnecting() { 355 return isReady() && ((mState == DctConstants.State.CONNECTED) 356 || (mState == DctConstants.State.CONNECTING) 357 || (mState == DctConstants.State.SCANNING) 358 || (mState == DctConstants.State.RETRYING)); 359 } 360 361 /** 362 * Set data call enabled/disabled state. 363 * @param enabled True if data call is enabled 364 */ 365 public void setEnabled(boolean enabled) { 366 if (DBG) { 367 log("set enabled as " + enabled + ", current state is " + mDataEnabled.get()); 368 } 369 mDataEnabled.set(enabled); 370 } 371 372 /** 373 * Check if the data call is enabled or not. 374 * @return True if enabled 375 */ 376 public boolean isEnabled() { 377 return mDataEnabled.get(); 378 } 379 380 public void setDependencyMet(boolean met) { 381 if (DBG) { 382 log("set mDependencyMet as " + met + " current state is " + mDependencyMet.get()); 383 } 384 mDependencyMet.set(met); 385 } 386 387 public boolean getDependencyMet() { 388 return mDependencyMet.get(); 389 } 390 391 public boolean isProvisioningApn() { 392 String provisioningApn = mPhone.getContext().getResources() 393 .getString(R.string.mobile_provisioning_apn); 394 if (!TextUtils.isEmpty(provisioningApn) && 395 (mApnSetting != null) && (mApnSetting.apn != null)) { 396 return (mApnSetting.apn.equals(provisioningApn)); 397 } else { 398 return false; 399 } 400 } 401 402 private final ArrayList<LocalLog> mLocalLogs = new ArrayList<>(); 403 private final ArrayList<NetworkRequest> mNetworkRequests = new ArrayList<>(); 404 private final LocalLog mStateLocalLog = new LocalLog(50); 405 406 public void requestLog(String str) { 407 synchronized (mRefCountLock) { 408 for (LocalLog l : mLocalLogs) { 409 l.log(str); 410 } 411 } 412 } 413 414 public void requestNetwork(NetworkRequest networkRequest, LocalLog log) { 415 synchronized (mRefCountLock) { 416 if (mLocalLogs.contains(log) || mNetworkRequests.contains(networkRequest)) { 417 log.log("ApnContext.requestNetwork has duplicate add - " + mNetworkRequests.size()); 418 } else { 419 mLocalLogs.add(log); 420 mNetworkRequests.add(networkRequest); 421 mDcTracker.setEnabled(apnIdForApnName(mApnType), true); 422 } 423 } 424 } 425 426 public void releaseNetwork(NetworkRequest networkRequest, LocalLog log) { 427 synchronized (mRefCountLock) { 428 if (mLocalLogs.contains(log) == false) { 429 log.log("ApnContext.releaseNetwork can't find this log"); 430 } else { 431 mLocalLogs.remove(log); 432 } 433 if (mNetworkRequests.contains(networkRequest) == false) { 434 log.log("ApnContext.releaseNetwork can't find this request (" 435 + networkRequest + ")"); 436 } else { 437 mNetworkRequests.remove(networkRequest); 438 log.log("ApnContext.releaseNetwork left with " + mNetworkRequests.size() + 439 " requests."); 440 if (mNetworkRequests.size() == 0) { 441 mDcTracker.setEnabled(apnIdForApnName(mApnType), false); 442 } 443 } 444 } 445 } 446 447 public List<NetworkRequest> getNetworkRequests() { 448 synchronized (mRefCountLock) { 449 return new ArrayList<NetworkRequest>(mNetworkRequests); 450 } 451 } 452 453 public boolean hasNoRestrictedRequests(boolean excludeDun) { 454 synchronized (mRefCountLock) { 455 for (NetworkRequest nr : mNetworkRequests) { 456 if (excludeDun && 457 nr.networkCapabilities.hasCapability( 458 NetworkCapabilities.NET_CAPABILITY_DUN)) { 459 continue; 460 } 461 if (nr.networkCapabilities.hasCapability( 462 NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) == false) { 463 return false; 464 } 465 } 466 } 467 return true; 468 } 469 470 private final SparseIntArray mRetriesLeftPerErrorCode = new SparseIntArray(); 471 472 public void resetErrorCodeRetries() { 473 requestLog("ApnContext.resetErrorCodeRetries"); 474 if (DBG) log("ApnContext.resetErrorCodeRetries"); 475 476 String[] config = mPhone.getContext().getResources().getStringArray( 477 com.android.internal.R.array.config_cell_retries_per_error_code); 478 synchronized (mRetriesLeftPerErrorCode) { 479 mRetriesLeftPerErrorCode.clear(); 480 481 for (String c : config) { 482 String errorValue[] = c.split(","); 483 if (errorValue != null && errorValue.length == 2) { 484 int count = 0; 485 int errorCode = 0; 486 try { 487 errorCode = Integer.parseInt(errorValue[0]); 488 count = Integer.parseInt(errorValue[1]); 489 } catch (NumberFormatException e) { 490 log("Exception parsing config_retries_per_error_code: " + e); 491 continue; 492 } 493 if (count > 0 && errorCode > 0) { 494 mRetriesLeftPerErrorCode.put(errorCode, count); 495 } 496 } else { 497 log("Exception parsing config_retries_per_error_code: " + c); 498 } 499 } 500 } 501 } 502 503 public boolean restartOnError(int errorCode) { 504 boolean result = false; 505 int retriesLeft = 0; 506 synchronized(mRetriesLeftPerErrorCode) { 507 retriesLeft = mRetriesLeftPerErrorCode.get(errorCode); 508 switch (retriesLeft) { 509 case 0: { 510 // not set, never restart modem 511 break; 512 } 513 case 1: { 514 resetErrorCodeRetries(); 515 result = true; 516 break; 517 } 518 default: { 519 mRetriesLeftPerErrorCode.put(errorCode, retriesLeft - 1); 520 result = false; 521 } 522 } 523 } 524 String str = "ApnContext.restartOnError(" + errorCode + ") found " + retriesLeft + 525 " and returned " + result; 526 if (DBG) log(str); 527 requestLog(str); 528 return result; 529 } 530 531 public int incAndGetConnectionGeneration() { 532 return mConnectionGeneration.incrementAndGet(); 533 } 534 535 public int getConnectionGeneration() { 536 return mConnectionGeneration.get(); 537 } 538 539 long getRetryAfterDisconnectDelay() { 540 return mRetryManager.getRetryAfterDisconnectDelay(); 541 } 542 543 public static int apnIdForType(int networkType) { 544 switch (networkType) { 545 case ConnectivityManager.TYPE_MOBILE: 546 return DctConstants.APN_DEFAULT_ID; 547 case ConnectivityManager.TYPE_MOBILE_MMS: 548 return DctConstants.APN_MMS_ID; 549 case ConnectivityManager.TYPE_MOBILE_SUPL: 550 return DctConstants.APN_SUPL_ID; 551 case ConnectivityManager.TYPE_MOBILE_DUN: 552 return DctConstants.APN_DUN_ID; 553 case ConnectivityManager.TYPE_MOBILE_FOTA: 554 return DctConstants.APN_FOTA_ID; 555 case ConnectivityManager.TYPE_MOBILE_IMS: 556 return DctConstants.APN_IMS_ID; 557 case ConnectivityManager.TYPE_MOBILE_CBS: 558 return DctConstants.APN_CBS_ID; 559 case ConnectivityManager.TYPE_MOBILE_IA: 560 return DctConstants.APN_IA_ID; 561 case ConnectivityManager.TYPE_MOBILE_EMERGENCY: 562 return DctConstants.APN_EMERGENCY_ID; 563 default: 564 return DctConstants.APN_INVALID_ID; 565 } 566 } 567 568 public static int apnIdForNetworkRequest(NetworkRequest nr) { 569 NetworkCapabilities nc = nr.networkCapabilities; 570 // For now, ignore the bandwidth stuff 571 if (nc.getTransportTypes().length > 0 && 572 nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) == false) { 573 return DctConstants.APN_INVALID_ID; 574 } 575 576 // in the near term just do 1-1 matches. 577 // TODO - actually try to match the set of capabilities 578 int apnId = DctConstants.APN_INVALID_ID; 579 boolean error = false; 580 581 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) { 582 apnId = DctConstants.APN_DEFAULT_ID; 583 } 584 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) { 585 if (apnId != DctConstants.APN_INVALID_ID) error = true; 586 apnId = DctConstants.APN_MMS_ID; 587 } 588 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)) { 589 if (apnId != DctConstants.APN_INVALID_ID) error = true; 590 apnId = DctConstants.APN_SUPL_ID; 591 } 592 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN)) { 593 if (apnId != DctConstants.APN_INVALID_ID) error = true; 594 apnId = DctConstants.APN_DUN_ID; 595 } 596 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_FOTA)) { 597 if (apnId != DctConstants.APN_INVALID_ID) error = true; 598 apnId = DctConstants.APN_FOTA_ID; 599 } 600 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)) { 601 if (apnId != DctConstants.APN_INVALID_ID) error = true; 602 apnId = DctConstants.APN_IMS_ID; 603 } 604 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)) { 605 if (apnId != DctConstants.APN_INVALID_ID) error = true; 606 apnId = DctConstants.APN_CBS_ID; 607 } 608 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_IA)) { 609 if (apnId != DctConstants.APN_INVALID_ID) error = true; 610 apnId = DctConstants.APN_IA_ID; 611 } 612 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_RCS)) { 613 if (apnId != DctConstants.APN_INVALID_ID) error = true; 614 615 Rlog.d(SLOG_TAG, "RCS APN type not yet supported"); 616 } 617 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_XCAP)) { 618 if (apnId != DctConstants.APN_INVALID_ID) error = true; 619 620 Rlog.d(SLOG_TAG, "XCAP APN type not yet supported"); 621 } 622 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_EIMS)) { 623 if (apnId != DctConstants.APN_INVALID_ID) error = true; 624 apnId = DctConstants.APN_EMERGENCY_ID; 625 } 626 if (error) { 627 // TODO: If this error condition is removed, the framework's handling of 628 // NET_CAPABILITY_NOT_RESTRICTED will need to be updated so requests for 629 // say FOTA and INTERNET are marked as restricted. This is not how 630 // NetworkCapabilities.maybeMarkCapabilitiesRestricted currently works. 631 Rlog.d(SLOG_TAG, "Multiple apn types specified in request - result is unspecified!"); 632 } 633 if (apnId == DctConstants.APN_INVALID_ID) { 634 Rlog.d(SLOG_TAG, "Unsupported NetworkRequest in Telephony: nr=" + nr); 635 } 636 return apnId; 637 } 638 639 // TODO - kill The use of these strings 640 public static int apnIdForApnName(String type) { 641 switch (type) { 642 case PhoneConstants.APN_TYPE_DEFAULT: 643 return DctConstants.APN_DEFAULT_ID; 644 case PhoneConstants.APN_TYPE_MMS: 645 return DctConstants.APN_MMS_ID; 646 case PhoneConstants.APN_TYPE_SUPL: 647 return DctConstants.APN_SUPL_ID; 648 case PhoneConstants.APN_TYPE_DUN: 649 return DctConstants.APN_DUN_ID; 650 case PhoneConstants.APN_TYPE_HIPRI: 651 return DctConstants.APN_HIPRI_ID; 652 case PhoneConstants.APN_TYPE_IMS: 653 return DctConstants.APN_IMS_ID; 654 case PhoneConstants.APN_TYPE_FOTA: 655 return DctConstants.APN_FOTA_ID; 656 case PhoneConstants.APN_TYPE_CBS: 657 return DctConstants.APN_CBS_ID; 658 case PhoneConstants.APN_TYPE_IA: 659 return DctConstants.APN_IA_ID; 660 case PhoneConstants.APN_TYPE_EMERGENCY: 661 return DctConstants.APN_EMERGENCY_ID; 662 default: 663 return DctConstants.APN_INVALID_ID; 664 } 665 } 666 667 private static String apnNameForApnId(int id) { 668 switch (id) { 669 case DctConstants.APN_DEFAULT_ID: 670 return PhoneConstants.APN_TYPE_DEFAULT; 671 case DctConstants.APN_MMS_ID: 672 return PhoneConstants.APN_TYPE_MMS; 673 case DctConstants.APN_SUPL_ID: 674 return PhoneConstants.APN_TYPE_SUPL; 675 case DctConstants.APN_DUN_ID: 676 return PhoneConstants.APN_TYPE_DUN; 677 case DctConstants.APN_HIPRI_ID: 678 return PhoneConstants.APN_TYPE_HIPRI; 679 case DctConstants.APN_IMS_ID: 680 return PhoneConstants.APN_TYPE_IMS; 681 case DctConstants.APN_FOTA_ID: 682 return PhoneConstants.APN_TYPE_FOTA; 683 case DctConstants.APN_CBS_ID: 684 return PhoneConstants.APN_TYPE_CBS; 685 case DctConstants.APN_IA_ID: 686 return PhoneConstants.APN_TYPE_IA; 687 case DctConstants.APN_EMERGENCY_ID: 688 return PhoneConstants.APN_TYPE_EMERGENCY; 689 default: 690 Rlog.d(SLOG_TAG, "Unknown id (" + id + ") in apnIdToType"); 691 return PhoneConstants.APN_TYPE_DEFAULT; 692 } 693 } 694 695 @Override 696 public synchronized String toString() { 697 // We don't print mDataConnection because its recursive. 698 return "{mApnType=" + mApnType + " mState=" + getState() + " mWaitingApns={" + 699 mRetryManager.getWaitingApns() + "}" + " mApnSetting={" + mApnSetting + 700 "} mReason=" + mReason + " mDataEnabled=" + mDataEnabled + " mDependencyMet=" + 701 mDependencyMet + "}"; 702 } 703 704 private void log(String s) { 705 Rlog.d(LOG_TAG, "[ApnContext:" + mApnType + "] " + s); 706 } 707 708 public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) { 709 final IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " "); 710 synchronized (mRefCountLock) { 711 pw.println(toString()); 712 if (mNetworkRequests.size() > 0) { 713 pw.println("NetworkRequests:"); 714 pw.increaseIndent(); 715 for (NetworkRequest nr : mNetworkRequests) { 716 pw.println(nr); 717 } 718 pw.decreaseIndent(); 719 } 720 pw.increaseIndent(); 721 for (LocalLog l : mLocalLogs) { 722 l.dump(fd, pw, args); 723 pw.println("-----"); 724 } 725 pw.decreaseIndent(); 726 pw.println("Historical APN state:"); 727 pw.increaseIndent(); 728 mStateLocalLog.dump(fd, pw, args); 729 pw.decreaseIndent(); 730 pw.println(mRetryManager); 731 pw.println("--------------------------"); 732 } 733 } 734 } 735