Home | History | Annotate | Download | only in dataconnection
      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