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 package com.android.internal.telephony.dataconnection;
     17 
     18 import android.content.Context;
     19 import android.content.res.Resources;
     20 import android.os.PersistableBundle;
     21 import android.telephony.CarrierConfigManager;
     22 
     23 import java.util.HashMap;
     24 import java.util.HashSet;
     25 
     26 /**
     27  * Returned as the reason for a connection failure as defined
     28  * by RIL_DataCallFailCause in ril.h and some local errors.
     29  */
     30 public enum DcFailCause {
     31     NONE(0),
     32 
     33     // This series of errors as specified by the standards
     34     // specified in ril.h
     35     OPERATOR_BARRED(0x08),                  /* no retry */
     36     NAS_SIGNALLING(0x0E),
     37     LLC_SNDCP(0x19),
     38     INSUFFICIENT_RESOURCES(0x1A),
     39     MISSING_UNKNOWN_APN(0x1B),              /* no retry */
     40     UNKNOWN_PDP_ADDRESS_TYPE(0x1C),         /* no retry */
     41     USER_AUTHENTICATION(0x1D),              /* no retry */
     42     ACTIVATION_REJECT_GGSN(0x1E),           /* no retry */
     43     ACTIVATION_REJECT_UNSPECIFIED(0x1F),
     44     SERVICE_OPTION_NOT_SUPPORTED(0x20),     /* no retry */
     45     SERVICE_OPTION_NOT_SUBSCRIBED(0x21),    /* no retry */
     46     SERVICE_OPTION_OUT_OF_ORDER(0x22),
     47     NSAPI_IN_USE(0x23),                     /* no retry */
     48     REGULAR_DEACTIVATION(0x24),             /* possibly restart radio, based on config */
     49     QOS_NOT_ACCEPTED(0x25),
     50     NETWORK_FAILURE(0x26),
     51     UMTS_REACTIVATION_REQ(0x27),
     52     FEATURE_NOT_SUPP(0x28),
     53     TFT_SEMANTIC_ERROR(0x29),
     54     TFT_SYTAX_ERROR(0x2A),
     55     UNKNOWN_PDP_CONTEXT(0x2B),
     56     FILTER_SEMANTIC_ERROR(0x2C),
     57     FILTER_SYTAX_ERROR(0x2D),
     58     PDP_WITHOUT_ACTIVE_TFT(0x2E),
     59     ONLY_IPV4_ALLOWED(0x32),                /* no retry */
     60     ONLY_IPV6_ALLOWED(0x33),                /* no retry */
     61     ONLY_SINGLE_BEARER_ALLOWED(0x34),
     62     ESM_INFO_NOT_RECEIVED(0x35),
     63     PDN_CONN_DOES_NOT_EXIST(0x36),
     64     MULTI_CONN_TO_SAME_PDN_NOT_ALLOWED(0x37),
     65     MAX_ACTIVE_PDP_CONTEXT_REACHED(0x41),
     66     UNSUPPORTED_APN_IN_CURRENT_PLMN(0x42),
     67     INVALID_TRANSACTION_ID(0x51),
     68     MESSAGE_INCORRECT_SEMANTIC(0x5F),
     69     INVALID_MANDATORY_INFO(0x60),
     70     MESSAGE_TYPE_UNSUPPORTED(0x61),
     71     MSG_TYPE_NONCOMPATIBLE_STATE(0x62),
     72     UNKNOWN_INFO_ELEMENT(0x63),
     73     CONDITIONAL_IE_ERROR(0x64),
     74     MSG_AND_PROTOCOL_STATE_UNCOMPATIBLE(0x65),
     75     PROTOCOL_ERRORS(0x6F),                  /* no retry */
     76     APN_TYPE_CONFLICT(0x70),
     77     INVALID_PCSCF_ADDR(0x71),
     78     INTERNAL_CALL_PREEMPT_BY_HIGH_PRIO_APN(0x72),
     79     EMM_ACCESS_BARRED(0x73),
     80     EMERGENCY_IFACE_ONLY(0x74),
     81     IFACE_MISMATCH(0x75),
     82     COMPANION_IFACE_IN_USE(0x76),
     83     IP_ADDRESS_MISMATCH(0x77),
     84     IFACE_AND_POL_FAMILY_MISMATCH(0x78),
     85     EMM_ACCESS_BARRED_INFINITE_RETRY(0x79),
     86     AUTH_FAILURE_ON_EMERGENCY_CALL(0x7A),
     87 
     88     // OEM sepecific error codes. To be used by OEMs when they don't
     89     // want to reveal error code which would be replaced by ERROR_UNSPECIFIED
     90     OEM_DCFAILCAUSE_1(0x1001),
     91     OEM_DCFAILCAUSE_2(0x1002),
     92     OEM_DCFAILCAUSE_3(0x1003),
     93     OEM_DCFAILCAUSE_4(0x1004),
     94     OEM_DCFAILCAUSE_5(0x1005),
     95     OEM_DCFAILCAUSE_6(0x1006),
     96     OEM_DCFAILCAUSE_7(0x1007),
     97     OEM_DCFAILCAUSE_8(0x1008),
     98     OEM_DCFAILCAUSE_9(0x1009),
     99     OEM_DCFAILCAUSE_10(0x100A),
    100     OEM_DCFAILCAUSE_11(0x100B),
    101     OEM_DCFAILCAUSE_12(0x100C),
    102     OEM_DCFAILCAUSE_13(0x100D),
    103     OEM_DCFAILCAUSE_14(0x100E),
    104     OEM_DCFAILCAUSE_15(0x100F),
    105 
    106     // Local errors generated by Vendor RIL
    107     // specified in ril.h
    108     REGISTRATION_FAIL(-1),
    109     GPRS_REGISTRATION_FAIL(-2),
    110     SIGNAL_LOST(-3),                        /* no retry */
    111     PREF_RADIO_TECH_CHANGED(-4),
    112     RADIO_POWER_OFF(-5),                    /* no retry */
    113     TETHERED_CALL_ACTIVE(-6),               /* no retry */
    114     ERROR_UNSPECIFIED(0xFFFF),
    115 
    116     // Errors generated by the Framework
    117     // specified here
    118     UNKNOWN(0x10000),
    119     RADIO_NOT_AVAILABLE(0x10001),                   /* no retry */
    120     UNACCEPTABLE_NETWORK_PARAMETER(0x10002),        /* no retry */
    121     CONNECTION_TO_DATACONNECTIONAC_BROKEN(0x10003),
    122     LOST_CONNECTION(0x10004),
    123     RESET_BY_FRAMEWORK(0x10005);
    124 
    125     private final int mErrorCode;
    126     private static final HashMap<Integer, DcFailCause> sErrorCodeToFailCauseMap;
    127     static {
    128         sErrorCodeToFailCauseMap = new HashMap<Integer, DcFailCause>();
    129         for (DcFailCause fc : values()) {
    130             sErrorCodeToFailCauseMap.put(fc.getErrorCode(), fc);
    131         }
    132     }
    133 
    134     /**
    135      * Map of subId -> set of data call setup permanent failure for the carrier.
    136      */
    137     private static final HashMap<Integer, HashSet<DcFailCause>> sPermanentFailureCache =
    138             new HashMap<>();
    139 
    140     DcFailCause(int errorCode) {
    141         mErrorCode = errorCode;
    142     }
    143 
    144     public int getErrorCode() {
    145         return mErrorCode;
    146     }
    147 
    148     /**
    149      * Returns whether or not the radio has failed and also needs to be restarted.
    150      * By default, we do not restart radio on REGULAR_DEACTIVATION.
    151      *
    152      * @param context device context
    153      * @param subId subscription id
    154      * @return true if the radio has failed and the carrier requres restart, otherwise false
    155      */
    156     public boolean isRestartRadioFail(Context context, int subId) {
    157         if (this == REGULAR_DEACTIVATION) {
    158             CarrierConfigManager configManager = (CarrierConfigManager)
    159                     context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
    160             if (configManager != null) {
    161                 PersistableBundle b = configManager.getConfigForSubId(subId);
    162                 if (b != null) {
    163                     return b.getBoolean(CarrierConfigManager.
    164                             KEY_RESTART_RADIO_ON_PDP_FAIL_REGULAR_DEACTIVATION_BOOL);
    165                 }
    166             }
    167         }
    168         return false;
    169     }
    170 
    171     public boolean isPermanentFailure(Context context, int subId) {
    172 
    173         synchronized (sPermanentFailureCache) {
    174 
    175             HashSet<DcFailCause> permanentFailureSet = sPermanentFailureCache.get(subId);
    176 
    177             // In case of cache miss, we need to look up the settings from carrier config.
    178             if (permanentFailureSet == null) {
    179                 // Retrieve the permanent failure from carrier config
    180                 CarrierConfigManager configManager = (CarrierConfigManager)
    181                         context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
    182                 if (configManager != null) {
    183                     PersistableBundle b = configManager.getConfigForSubId(subId);
    184                     if (b != null) {
    185                         String[] permanentFailureStrings = b.getStringArray(CarrierConfigManager.
    186                                 KEY_CARRIER_DATA_CALL_PERMANENT_FAILURE_STRINGS);
    187 
    188                         if (permanentFailureStrings != null) {
    189                             permanentFailureSet = new HashSet<>();
    190                             for (String failure : permanentFailureStrings) {
    191                                 permanentFailureSet.add(DcFailCause.valueOf(failure));
    192                             }
    193                         }
    194                     }
    195                 }
    196 
    197                 // If we are not able to find the configuration from carrier config, use the default
    198                 // ones.
    199                 if (permanentFailureSet == null) {
    200                     permanentFailureSet = new HashSet<DcFailCause>() {
    201                         {
    202                             add(OPERATOR_BARRED);
    203                             add(MISSING_UNKNOWN_APN);
    204                             add(UNKNOWN_PDP_ADDRESS_TYPE);
    205                             add(USER_AUTHENTICATION);
    206                             add(ACTIVATION_REJECT_GGSN);
    207                             add(SERVICE_OPTION_NOT_SUPPORTED);
    208                             add(SERVICE_OPTION_NOT_SUBSCRIBED);
    209                             add(NSAPI_IN_USE);
    210                             add(ONLY_IPV4_ALLOWED);
    211                             add(ONLY_IPV6_ALLOWED);
    212                             add(PROTOCOL_ERRORS);
    213                             add(RADIO_POWER_OFF);
    214                             add(TETHERED_CALL_ACTIVE);
    215                             add(RADIO_NOT_AVAILABLE);
    216                             add(UNACCEPTABLE_NETWORK_PARAMETER);
    217                             add(SIGNAL_LOST);
    218                         }
    219                     };
    220                 }
    221 
    222                 sPermanentFailureCache.put(subId, permanentFailureSet);
    223             }
    224 
    225             return permanentFailureSet.contains(this);
    226         }
    227     }
    228 
    229     public boolean isEventLoggable() {
    230         return (this == OPERATOR_BARRED) || (this == INSUFFICIENT_RESOURCES) ||
    231                 (this == UNKNOWN_PDP_ADDRESS_TYPE) || (this == USER_AUTHENTICATION) ||
    232                 (this == ACTIVATION_REJECT_GGSN) || (this == ACTIVATION_REJECT_UNSPECIFIED) ||
    233                 (this == SERVICE_OPTION_NOT_SUBSCRIBED) ||
    234                 (this == SERVICE_OPTION_NOT_SUPPORTED) ||
    235                 (this == SERVICE_OPTION_OUT_OF_ORDER) || (this == NSAPI_IN_USE) ||
    236                 (this == ONLY_IPV4_ALLOWED) || (this == ONLY_IPV6_ALLOWED) ||
    237                 (this == PROTOCOL_ERRORS) || (this == SIGNAL_LOST) ||
    238                 (this == RADIO_POWER_OFF) || (this == TETHERED_CALL_ACTIVE) ||
    239                 (this == UNACCEPTABLE_NETWORK_PARAMETER);
    240     }
    241 
    242     public static DcFailCause fromInt(int errorCode) {
    243         DcFailCause fc = sErrorCodeToFailCauseMap.get(errorCode);
    244         if (fc == null) {
    245             fc = UNKNOWN;
    246         }
    247         return fc;
    248     }
    249 }
    250