1/* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.internal.telephony.dataconnection; 18 19import android.app.PendingIntent; 20import android.content.res.Resources; 21import android.net.ConnectivityManager; 22import android.net.NetworkCapabilities; 23import android.net.NetworkConfig; 24import android.net.NetworkRequest; 25import android.telephony.Rlog; 26import android.text.TextUtils; 27import android.util.LocalLog; 28import android.util.SparseIntArray; 29 30import com.android.internal.R; 31import com.android.internal.telephony.DctConstants; 32import com.android.internal.telephony.Phone; 33import com.android.internal.telephony.PhoneConstants; 34import com.android.internal.telephony.RetryManager; 35import com.android.internal.util.IndentingPrintWriter; 36 37import java.io.FileDescriptor; 38import java.io.PrintWriter; 39import java.util.ArrayDeque; 40import java.util.ArrayList; 41import java.util.List; 42import java.util.concurrent.atomic.AtomicBoolean; 43import java.util.concurrent.atomic.AtomicInteger; 44 45/** 46 * Maintain the Apn context 47 */ 48public class ApnContext { 49 50 public final String LOG_TAG; 51 private final static String SLOG_TAG = "ApnContext"; 52 53 protected static final boolean DBG = false; 54 55 private final Phone mPhone; 56 57 private final String mApnType; 58 59 private DctConstants.State mState; 60 61 public final int priority; 62 63 private ApnSetting mApnSetting; 64 65 DcAsyncChannel mDcAc; 66 67 String mReason; 68 69 PendingIntent mReconnectAlarmIntent; 70 71 /** 72 * user/app requested connection on this APN 73 */ 74 AtomicBoolean mDataEnabled; 75 76 private final Object mRefCountLock = new Object(); 77 private int mRefCount = 0; 78 79 /** 80 * carrier requirements met 81 */ 82 AtomicBoolean mDependencyMet; 83 84 private final DcTracker mDcTracker; 85 86 /** 87 * Remember this as a change in this value to a more permissive state 88 * should cause us to retry even permanent failures 89 */ 90 private boolean mConcurrentVoiceAndDataAllowed; 91 92 /** 93 * used to track a single connection request so disconnects can get ignored if 94 * obsolete. 95 */ 96 private final AtomicInteger mConnectionGeneration = new AtomicInteger(0); 97 98 /** 99 * Retry manager that handles the APN retry and delays. 100 */ 101 private final RetryManager mRetryManager; 102 103 /** 104 * AonContext constructor 105 * @param phone phone object 106 * @param apnType APN type (e.g. default, supl, mms, etc...) 107 * @param logTag Tag for logging 108 * @param config Network configuration 109 * @param tracker Data call tracker 110 */ 111 public ApnContext(Phone phone, String apnType, String logTag, NetworkConfig config, 112 DcTracker tracker) { 113 mPhone = phone; 114 mApnType = apnType; 115 mState = DctConstants.State.IDLE; 116 setReason(Phone.REASON_DATA_ENABLED); 117 mDataEnabled = new AtomicBoolean(false); 118 mDependencyMet = new AtomicBoolean(config.dependencyMet); 119 priority = config.priority; 120 LOG_TAG = logTag; 121 mDcTracker = tracker; 122 mRetryManager = new RetryManager(phone, apnType); 123 } 124 125 /** 126 * Get the APN type 127 * @return The APN type 128 */ 129 public String getApnType() { 130 return mApnType; 131 } 132 133 /** 134 * Get the data call async channel. 135 * @return The data call async channel 136 */ 137 public synchronized DcAsyncChannel getDcAc() { 138 return mDcAc; 139 } 140 141 /** 142 * Set the data call async channel. 143 * @param dcac The data call async channel 144 */ 145 public synchronized void setDataConnectionAc(DcAsyncChannel dcac) { 146 if (DBG) { 147 log("setDataConnectionAc: old dcac=" + mDcAc + " new dcac=" + dcac 148 + " this=" + this); 149 } 150 mDcAc = dcac; 151 } 152 153 /** 154 * Release data connection. 155 * @param reason The reason of releasing data connection 156 */ 157 public synchronized void releaseDataConnection(String reason) { 158 if (mDcAc != null) { 159 mDcAc.tearDown(this, reason, null); 160 mDcAc = null; 161 } 162 setState(DctConstants.State.IDLE); 163 } 164 165 /** 166 * Get the reconnect intent. 167 * @return The reconnect intent 168 */ 169 public synchronized PendingIntent getReconnectIntent() { 170 return mReconnectAlarmIntent; 171 } 172 173 /** 174 * Save the reconnect intent which can be used for cancelling later. 175 * @param intent The reconnect intent 176 */ 177 public synchronized void setReconnectIntent(PendingIntent intent) { 178 mReconnectAlarmIntent = intent; 179 } 180 181 /** 182 * Get the current APN setting. 183 * @return APN setting 184 */ 185 public synchronized ApnSetting getApnSetting() { 186 if (DBG) log("getApnSetting: apnSetting=" + mApnSetting); 187 return mApnSetting; 188 } 189 190 /** 191 * Set the APN setting. 192 * @param apnSetting APN setting 193 */ 194 public synchronized void setApnSetting(ApnSetting apnSetting) { 195 if (DBG) log("setApnSetting: apnSetting=" + apnSetting); 196 mApnSetting = apnSetting; 197 } 198 199 /** 200 * Set the list of APN candidates which will be used for data call setup later. 201 * @param waitingApns List of APN candidates 202 */ 203 public synchronized void setWaitingApns(ArrayList<ApnSetting> waitingApns) { 204 mRetryManager.setWaitingApns(waitingApns); 205 } 206 207 /** 208 * Get the next available APN to try. 209 * @return APN setting which will be used for data call setup. Return null if there is no 210 * APN can be retried. 211 */ 212 public ApnSetting getNextApnSetting() { 213 return mRetryManager.getNextApnSetting(); 214 } 215 216 /** 217 * Save the modem suggested delay for retrying the current APN. 218 * This method is called when we get the suggested delay from RIL. 219 * @param delay The delay in milliseconds 220 */ 221 public void setModemSuggestedDelay(long delay) { 222 mRetryManager.setModemSuggestedDelay(delay); 223 } 224 225 /** 226 * Get the delay for trying the next APN setting if the current one failed. 227 * @param failFastEnabled True if fail fast mode enabled. In this case we'll use a shorter 228 * delay. 229 * @return The delay in milliseconds 230 */ 231 public long getDelayForNextApn(boolean failFastEnabled) { 232 return mRetryManager.getDelayForNextApn(failFastEnabled || isFastRetryReason()); 233 } 234 235 /** 236 * Mark the current APN setting permanently failed, which means it will not be retried anymore. 237 * @param apn APN setting 238 */ 239 public void markApnPermanentFailed(ApnSetting apn) { 240 mRetryManager.markApnPermanentFailed(apn); 241 } 242 243 /** 244 * Get the list of waiting APNs. 245 * @return the list of waiting APNs 246 */ 247 public ArrayList<ApnSetting> getWaitingApns() { 248 return mRetryManager.getWaitingApns(); 249 } 250 251 /** 252 * Save the state indicating concurrent voice/data allowed. 253 * @param allowed True if concurrent voice/data is allowed 254 */ 255 public synchronized void setConcurrentVoiceAndDataAllowed(boolean allowed) { 256 mConcurrentVoiceAndDataAllowed = allowed; 257 } 258 259 /** 260 * Get the state indicating concurrent voice/data allowed. 261 * @return True if concurrent voice/data is allowed 262 */ 263 public synchronized boolean isConcurrentVoiceAndDataAllowed() { 264 return mConcurrentVoiceAndDataAllowed; 265 } 266 267 /** 268 * Set the current data call state. 269 * @param s Current data call state 270 */ 271 public synchronized void setState(DctConstants.State s) { 272 if (DBG) { 273 log("setState: " + s + ", previous state:" + mState); 274 } 275 276 mState = s; 277 278 if (mState == DctConstants.State.FAILED) { 279 if (mRetryManager.getWaitingApns() != null) { 280 mRetryManager.getWaitingApns().clear(); // when teardown the connection and set to IDLE 281 } 282 } 283 } 284 285 /** 286 * Get the current data call state. 287 * @return The current data call state 288 */ 289 public synchronized DctConstants.State getState() { 290 return mState; 291 } 292 293 /** 294 * Check whether the data call is disconnected or not. 295 * @return True if the data call is disconnected 296 */ 297 public boolean isDisconnected() { 298 DctConstants.State currentState = getState(); 299 return ((currentState == DctConstants.State.IDLE) || 300 currentState == DctConstants.State.FAILED); 301 } 302 303 /** 304 * Set the reason for data call connection. 305 * @param reason Reason for data call connection 306 */ 307 public synchronized void setReason(String reason) { 308 if (DBG) { 309 log("set reason as " + reason + ",current state " + mState); 310 } 311 mReason = reason; 312 } 313 314 /** 315 * Get the reason for data call connection. 316 * @return The reason for data call connection 317 */ 318 public synchronized String getReason() { 319 return mReason; 320 } 321 322 /** 323 * Check if ready for data call connection 324 * @return True if ready, otherwise false. 325 */ 326 public boolean isReady() { 327 return mDataEnabled.get() && mDependencyMet.get(); 328 } 329 330 /** 331 * Check if the data call is in the state which allow connecting. 332 * @return True if allowed, otherwise false. 333 */ 334 public boolean isConnectable() { 335 return isReady() && ((mState == DctConstants.State.IDLE) 336 || (mState == DctConstants.State.SCANNING) 337 || (mState == DctConstants.State.RETRYING) 338 || (mState == DctConstants.State.FAILED)); 339 } 340 341 /** 342 * Check if apn reason is fast retry reason which should apply shorter delay between apn re-try. 343 * @return True if it is fast retry reason, otherwise false. 344 */ 345 private boolean isFastRetryReason() { 346 return Phone.REASON_NW_TYPE_CHANGED.equals(mReason) || 347 Phone.REASON_APN_CHANGED.equals(mReason); 348 } 349 350 /** Check if the data call is in connected or connecting state. 351 * @return True if the data call is in connected or connecting state 352 */ 353 public boolean isConnectedOrConnecting() { 354 return isReady() && ((mState == DctConstants.State.CONNECTED) 355 || (mState == DctConstants.State.CONNECTING) 356 || (mState == DctConstants.State.SCANNING) 357 || (mState == DctConstants.State.RETRYING)); 358 } 359 360 /** 361 * Set data call enabled/disabled state. 362 * @param enabled True if data call is enabled 363 */ 364 public void setEnabled(boolean enabled) { 365 if (DBG) { 366 log("set enabled as " + enabled + ", current state is " + mDataEnabled.get()); 367 } 368 mDataEnabled.set(enabled); 369 } 370 371 /** 372 * Check if the data call is enabled or not. 373 * @return True if enabled 374 */ 375 public boolean isEnabled() { 376 return mDataEnabled.get(); 377 } 378 379 public void setDependencyMet(boolean met) { 380 if (DBG) { 381 log("set mDependencyMet as " + met + " current state is " + mDependencyMet.get()); 382 } 383 mDependencyMet.set(met); 384 } 385 386 public boolean getDependencyMet() { 387 return mDependencyMet.get(); 388 } 389 390 public boolean isProvisioningApn() { 391 String provisioningApn = mPhone.getContext().getResources() 392 .getString(R.string.mobile_provisioning_apn); 393 if (!TextUtils.isEmpty(provisioningApn) && 394 (mApnSetting != null) && (mApnSetting.apn != null)) { 395 return (mApnSetting.apn.equals(provisioningApn)); 396 } else { 397 return false; 398 } 399 } 400 401 private final ArrayList<LocalLog> mLocalLogs = new ArrayList<>(); 402 private final ArrayList<NetworkRequest> mNetworkRequests = new ArrayList<>(); 403 private final ArrayDeque<LocalLog> mHistoryLogs = new ArrayDeque<>(); 404 private final static int MAX_HISTORY_LOG_COUNT = 4; 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 public long getInterApnDelay(boolean failFastEnabled) { 540 return mRetryManager.getInterApnDelay(failFastEnabled || isFastRetryReason()); 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 } 724 if (mHistoryLogs.size() > 0) pw.println("Historical Logs:"); 725 for (LocalLog l : mHistoryLogs) { 726 l.dump(fd, pw, args); 727 } 728 pw.decreaseIndent(); 729 pw.println("mRetryManager={" + mRetryManager.toString() + "}"); 730 } 731 } 732} 733