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()) {
fc.getErrorCode()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 
DcFailCause(int errorCode)140     DcFailCause(int errorCode) {
141         mErrorCode = errorCode;
142     }
143 
getErrorCode()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      */
isRestartRadioFail(Context context, int subId)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 
isPermanentFailure(Context context, int subId)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 
isEventLoggable()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 
fromInt(int errorCode)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