ApnContext.java revision 692640f429efa8e292c6261472b2c682e1079f8e
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); 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 /** Check if the data call is in connected or connecting state. 342 * @return True if the data call is in connected or connecting state 343 */ 344 public boolean isConnectedOrConnecting() { 345 return isReady() && ((mState == DctConstants.State.CONNECTED) 346 || (mState == DctConstants.State.CONNECTING) 347 || (mState == DctConstants.State.SCANNING) 348 || (mState == DctConstants.State.RETRYING)); 349 } 350 351 /** 352 * Set data call enabled/disabled state. 353 * @param enabled True if data call is enabled 354 */ 355 public void setEnabled(boolean enabled) { 356 if (DBG) { 357 log("set enabled as " + enabled + ", current state is " + mDataEnabled.get()); 358 } 359 mDataEnabled.set(enabled); 360 } 361 362 /** 363 * Check if the data call is enabled or not. 364 * @return True if enabled 365 */ 366 public boolean isEnabled() { 367 return mDataEnabled.get(); 368 } 369 370 public void setDependencyMet(boolean met) { 371 if (DBG) { 372 log("set mDependencyMet as " + met + " current state is " + mDependencyMet.get()); 373 } 374 mDependencyMet.set(met); 375 } 376 377 public boolean getDependencyMet() { 378 return mDependencyMet.get(); 379 } 380 381 public boolean isProvisioningApn() { 382 String provisioningApn = mPhone.getContext().getResources() 383 .getString(R.string.mobile_provisioning_apn); 384 if (!TextUtils.isEmpty(provisioningApn) && 385 (mApnSetting != null) && (mApnSetting.apn != null)) { 386 return (mApnSetting.apn.equals(provisioningApn)); 387 } else { 388 return false; 389 } 390 } 391 392 private final ArrayList<LocalLog> mLocalLogs = new ArrayList<>(); 393 private final ArrayList<NetworkRequest> mNetworkRequests = new ArrayList<>(); 394 private final ArrayDeque<LocalLog> mHistoryLogs = new ArrayDeque<>(); 395 private final static int MAX_HISTORY_LOG_COUNT = 4; 396 397 public void requestLog(String str) { 398 synchronized (mRefCountLock) { 399 for (LocalLog l : mLocalLogs) { 400 l.log(str); 401 } 402 } 403 } 404 405 public void requestNetwork(NetworkRequest networkRequest, LocalLog log) { 406 synchronized (mRefCountLock) { 407 if (mLocalLogs.contains(log) || mNetworkRequests.contains(networkRequest)) { 408 log.log("ApnContext.requestNetwork has duplicate add - " + mNetworkRequests.size()); 409 } else { 410 mLocalLogs.add(log); 411 mNetworkRequests.add(networkRequest); 412 if (mNetworkRequests.size() == 1) { 413 mDcTracker.setEnabled(apnIdForApnName(mApnType), true); 414 } 415 } 416 } 417 } 418 419 public void releaseNetwork(NetworkRequest networkRequest, LocalLog log) { 420 synchronized (mRefCountLock) { 421 if (mLocalLogs.contains(log) == false) { 422 log.log("ApnContext.releaseNetwork can't find this log"); 423 } else { 424 mLocalLogs.remove(log); 425 } 426 if (mNetworkRequests.contains(networkRequest) == false) { 427 log.log("ApnContext.releaseNetwork can't find this request (" 428 + networkRequest + ")"); 429 } else { 430 mNetworkRequests.remove(networkRequest); 431 log.log("ApnContext.releaseNetwork left with " + mNetworkRequests.size() + 432 " requests."); 433 if (mNetworkRequests.size() == 0) { 434 mDcTracker.setEnabled(apnIdForApnName(mApnType), false); 435 } 436 } 437 } 438 } 439 440 public List<NetworkRequest> getNetworkRequests() { 441 synchronized (mRefCountLock) { 442 return new ArrayList<NetworkRequest>(mNetworkRequests); 443 } 444 } 445 446 public boolean hasNoRestrictedRequests() { 447 synchronized (mRefCountLock) { 448 for (NetworkRequest nr : mNetworkRequests) { 449 if (nr.networkCapabilities.hasCapability( 450 NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) == false) { 451 return false; 452 } 453 } 454 } 455 return true; 456 } 457 458 private final SparseIntArray mRetriesLeftPerErrorCode = new SparseIntArray(); 459 460 public void resetErrorCodeRetries() { 461 requestLog("ApnContext.resetErrorCodeRetries"); 462 if (DBG) log("ApnContext.resetErrorCodeRetries"); 463 464 String[] config = mPhone.getContext().getResources().getStringArray( 465 com.android.internal.R.array.config_cell_retries_per_error_code); 466 synchronized (mRetriesLeftPerErrorCode) { 467 mRetriesLeftPerErrorCode.clear(); 468 469 for (String c : config) { 470 String errorValue[] = c.split(","); 471 if (errorValue != null && errorValue.length == 2) { 472 int count = 0; 473 int errorCode = 0; 474 try { 475 errorCode = Integer.parseInt(errorValue[0]); 476 count = Integer.parseInt(errorValue[1]); 477 } catch (NumberFormatException e) { 478 log("Exception parsing config_retries_per_error_code: " + e); 479 continue; 480 } 481 if (count > 0 && errorCode > 0) { 482 mRetriesLeftPerErrorCode.put(errorCode, count); 483 } 484 } else { 485 log("Exception parsing config_retries_per_error_code: " + c); 486 } 487 } 488 } 489 } 490 491 public boolean restartOnError(int errorCode) { 492 boolean result = false; 493 int retriesLeft = 0; 494 synchronized(mRetriesLeftPerErrorCode) { 495 retriesLeft = mRetriesLeftPerErrorCode.get(errorCode); 496 switch (retriesLeft) { 497 case 0: { 498 // not set, never restart modem 499 break; 500 } 501 case 1: { 502 resetErrorCodeRetries(); 503 result = true; 504 break; 505 } 506 default: { 507 mRetriesLeftPerErrorCode.put(errorCode, retriesLeft - 1); 508 result = false; 509 } 510 } 511 } 512 String str = "ApnContext.restartOnError(" + errorCode + ") found " + retriesLeft + 513 " and returned " + result; 514 if (DBG) log(str); 515 requestLog(str); 516 return result; 517 } 518 519 public int incAndGetConnectionGeneration() { 520 return mConnectionGeneration.incrementAndGet(); 521 } 522 523 public int getConnectionGeneration() { 524 return mConnectionGeneration.get(); 525 } 526 527 public long getInterApnDelay(boolean failFastEnabled) { 528 return mRetryManager.getInterApnDelay(failFastEnabled); 529 } 530 531 public static int apnIdForType(int networkType) { 532 switch (networkType) { 533 case ConnectivityManager.TYPE_MOBILE: 534 return DctConstants.APN_DEFAULT_ID; 535 case ConnectivityManager.TYPE_MOBILE_MMS: 536 return DctConstants.APN_MMS_ID; 537 case ConnectivityManager.TYPE_MOBILE_SUPL: 538 return DctConstants.APN_SUPL_ID; 539 case ConnectivityManager.TYPE_MOBILE_DUN: 540 return DctConstants.APN_DUN_ID; 541 case ConnectivityManager.TYPE_MOBILE_FOTA: 542 return DctConstants.APN_FOTA_ID; 543 case ConnectivityManager.TYPE_MOBILE_IMS: 544 return DctConstants.APN_IMS_ID; 545 case ConnectivityManager.TYPE_MOBILE_CBS: 546 return DctConstants.APN_CBS_ID; 547 case ConnectivityManager.TYPE_MOBILE_IA: 548 return DctConstants.APN_IA_ID; 549 case ConnectivityManager.TYPE_MOBILE_EMERGENCY: 550 return DctConstants.APN_EMERGENCY_ID; 551 default: 552 return DctConstants.APN_INVALID_ID; 553 } 554 } 555 556 public static int apnIdForNetworkRequest(NetworkRequest nr) { 557 NetworkCapabilities nc = nr.networkCapabilities; 558 // For now, ignore the bandwidth stuff 559 if (nc.getTransportTypes().length > 0 && 560 nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) == false) { 561 return DctConstants.APN_INVALID_ID; 562 } 563 564 // in the near term just do 1-1 matches. 565 // TODO - actually try to match the set of capabilities 566 int apnId = DctConstants.APN_INVALID_ID; 567 boolean error = false; 568 569 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) { 570 apnId = DctConstants.APN_DEFAULT_ID; 571 } 572 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) { 573 if (apnId != DctConstants.APN_INVALID_ID) error = true; 574 apnId = DctConstants.APN_MMS_ID; 575 } 576 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)) { 577 if (apnId != DctConstants.APN_INVALID_ID) error = true; 578 apnId = DctConstants.APN_SUPL_ID; 579 } 580 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN)) { 581 if (apnId != DctConstants.APN_INVALID_ID) error = true; 582 apnId = DctConstants.APN_DUN_ID; 583 } 584 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_FOTA)) { 585 if (apnId != DctConstants.APN_INVALID_ID) error = true; 586 apnId = DctConstants.APN_FOTA_ID; 587 } 588 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)) { 589 if (apnId != DctConstants.APN_INVALID_ID) error = true; 590 apnId = DctConstants.APN_IMS_ID; 591 } 592 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)) { 593 if (apnId != DctConstants.APN_INVALID_ID) error = true; 594 apnId = DctConstants.APN_CBS_ID; 595 } 596 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_IA)) { 597 if (apnId != DctConstants.APN_INVALID_ID) error = true; 598 apnId = DctConstants.APN_IA_ID; 599 } 600 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_RCS)) { 601 if (apnId != DctConstants.APN_INVALID_ID) error = true; 602 603 Rlog.d(SLOG_TAG, "RCS APN type not yet supported"); 604 } 605 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_XCAP)) { 606 if (apnId != DctConstants.APN_INVALID_ID) error = true; 607 608 Rlog.d(SLOG_TAG, "XCAP APN type not yet supported"); 609 } 610 if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_EIMS)) { 611 if (apnId != DctConstants.APN_INVALID_ID) error = true; 612 apnId = DctConstants.APN_MMS_ID; 613 } 614 if (error) { 615 // TODO: If this error condition is removed, the framework's handling of 616 // NET_CAPABILITY_NOT_RESTRICTED will need to be updated so requests for 617 // say FOTA and INTERNET are marked as restricted. This is not how 618 // NetworkCapabilities.maybeMarkCapabilitiesRestricted currently works. 619 Rlog.d(SLOG_TAG, "Multiple apn types specified in request - result is unspecified!"); 620 } 621 if (apnId == DctConstants.APN_INVALID_ID) { 622 Rlog.d(SLOG_TAG, "Unsupported NetworkRequest in Telephony: nr=" + nr); 623 } 624 return apnId; 625 } 626 627 // TODO - kill The use of these strings 628 public static int apnIdForApnName(String type) { 629 switch (type) { 630 case PhoneConstants.APN_TYPE_DEFAULT: 631 return DctConstants.APN_DEFAULT_ID; 632 case PhoneConstants.APN_TYPE_MMS: 633 return DctConstants.APN_MMS_ID; 634 case PhoneConstants.APN_TYPE_SUPL: 635 return DctConstants.APN_SUPL_ID; 636 case PhoneConstants.APN_TYPE_DUN: 637 return DctConstants.APN_DUN_ID; 638 case PhoneConstants.APN_TYPE_HIPRI: 639 return DctConstants.APN_HIPRI_ID; 640 case PhoneConstants.APN_TYPE_IMS: 641 return DctConstants.APN_IMS_ID; 642 case PhoneConstants.APN_TYPE_FOTA: 643 return DctConstants.APN_FOTA_ID; 644 case PhoneConstants.APN_TYPE_CBS: 645 return DctConstants.APN_CBS_ID; 646 case PhoneConstants.APN_TYPE_IA: 647 return DctConstants.APN_IA_ID; 648 case PhoneConstants.APN_TYPE_EMERGENCY: 649 return DctConstants.APN_EMERGENCY_ID; 650 default: 651 return DctConstants.APN_INVALID_ID; 652 } 653 } 654 655 private static String apnNameForApnId(int id) { 656 switch (id) { 657 case DctConstants.APN_DEFAULT_ID: 658 return PhoneConstants.APN_TYPE_DEFAULT; 659 case DctConstants.APN_MMS_ID: 660 return PhoneConstants.APN_TYPE_MMS; 661 case DctConstants.APN_SUPL_ID: 662 return PhoneConstants.APN_TYPE_SUPL; 663 case DctConstants.APN_DUN_ID: 664 return PhoneConstants.APN_TYPE_DUN; 665 case DctConstants.APN_HIPRI_ID: 666 return PhoneConstants.APN_TYPE_HIPRI; 667 case DctConstants.APN_IMS_ID: 668 return PhoneConstants.APN_TYPE_IMS; 669 case DctConstants.APN_FOTA_ID: 670 return PhoneConstants.APN_TYPE_FOTA; 671 case DctConstants.APN_CBS_ID: 672 return PhoneConstants.APN_TYPE_CBS; 673 case DctConstants.APN_IA_ID: 674 return PhoneConstants.APN_TYPE_IA; 675 case DctConstants.APN_EMERGENCY_ID: 676 return PhoneConstants.APN_TYPE_EMERGENCY; 677 default: 678 Rlog.d(SLOG_TAG, "Unknown id (" + id + ") in apnIdToType"); 679 return PhoneConstants.APN_TYPE_DEFAULT; 680 } 681 } 682 683 @Override 684 public synchronized String toString() { 685 // We don't print mDataConnection because its recursive. 686 return "{mApnType=" + mApnType + " mState=" + getState() + " mWaitingApns={" + 687 mRetryManager.getWaitingApns() + "}" + " mApnSetting={" + mApnSetting + 688 "} mReason=" + mReason + " mDataEnabled=" + mDataEnabled + " mDependencyMet=" + 689 mDependencyMet + "}"; 690 } 691 692 private void log(String s) { 693 Rlog.d(LOG_TAG, "[ApnContext:" + mApnType + "] " + s); 694 } 695 696 public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) { 697 final IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " "); 698 synchronized (mRefCountLock) { 699 pw.println(toString()); 700 if (mNetworkRequests.size() > 0) { 701 pw.println("NetworkRequests:"); 702 pw.increaseIndent(); 703 for (NetworkRequest nr : mNetworkRequests) { 704 pw.println(nr); 705 } 706 pw.decreaseIndent(); 707 } 708 pw.increaseIndent(); 709 for (LocalLog l : mLocalLogs) { 710 l.dump(fd, pw, args); 711 } 712 if (mHistoryLogs.size() > 0) pw.println("Historical Logs:"); 713 for (LocalLog l : mHistoryLogs) { 714 l.dump(fd, pw, args); 715 } 716 pw.decreaseIndent(); 717 pw.println("mRetryManager={" + mRetryManager.toString() + "}"); 718 } 719 } 720} 721