blob: b3762e5333430f1e3d67ac965555b736c6ac951d [file] [log] [blame]
/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.internal.telephony.dataconnection;
import android.content.Context;
import android.content.res.Resources;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import java.util.HashMap;
import java.util.HashSet;
/**
* Returned as the reason for a connection failure as defined
* by RIL_DataCallFailCause in ril.h and some local errors.
*/
public enum DcFailCause {
NONE(0),
// This series of errors as specified by the standards
// specified in ril.h
OPERATOR_BARRED(0x08), /* no retry */
NAS_SIGNALLING(0x0E),
LLC_SNDCP(0x19),
INSUFFICIENT_RESOURCES(0x1A),
MISSING_UNKNOWN_APN(0x1B), /* no retry */
UNKNOWN_PDP_ADDRESS_TYPE(0x1C), /* no retry */
USER_AUTHENTICATION(0x1D), /* no retry */
ACTIVATION_REJECT_GGSN(0x1E), /* no retry */
ACTIVATION_REJECT_UNSPECIFIED(0x1F),
SERVICE_OPTION_NOT_SUPPORTED(0x20), /* no retry */
SERVICE_OPTION_NOT_SUBSCRIBED(0x21), /* no retry */
SERVICE_OPTION_OUT_OF_ORDER(0x22),
NSAPI_IN_USE(0x23), /* no retry */
REGULAR_DEACTIVATION(0x24), /* possibly restart radio, based on config */
QOS_NOT_ACCEPTED(0x25),
NETWORK_FAILURE(0x26),
UMTS_REACTIVATION_REQ(0x27),
FEATURE_NOT_SUPP(0x28),
TFT_SEMANTIC_ERROR(0x29),
TFT_SYTAX_ERROR(0x2A),
UNKNOWN_PDP_CONTEXT(0x2B),
FILTER_SEMANTIC_ERROR(0x2C),
FILTER_SYTAX_ERROR(0x2D),
PDP_WITHOUT_ACTIVE_TFT(0x2E),
ONLY_IPV4_ALLOWED(0x32), /* no retry */
ONLY_IPV6_ALLOWED(0x33), /* no retry */
ONLY_SINGLE_BEARER_ALLOWED(0x34),
ESM_INFO_NOT_RECEIVED(0x35),
PDN_CONN_DOES_NOT_EXIST(0x36),
MULTI_CONN_TO_SAME_PDN_NOT_ALLOWED(0x37),
MAX_ACTIVE_PDP_CONTEXT_REACHED(0x41),
UNSUPPORTED_APN_IN_CURRENT_PLMN(0x42),
INVALID_TRANSACTION_ID(0x51),
MESSAGE_INCORRECT_SEMANTIC(0x5F),
INVALID_MANDATORY_INFO(0x60),
MESSAGE_TYPE_UNSUPPORTED(0x61),
MSG_TYPE_NONCOMPATIBLE_STATE(0x62),
UNKNOWN_INFO_ELEMENT(0x63),
CONDITIONAL_IE_ERROR(0x64),
MSG_AND_PROTOCOL_STATE_UNCOMPATIBLE(0x65),
PROTOCOL_ERRORS(0x6F), /* no retry */
APN_TYPE_CONFLICT(0x70),
INVALID_PCSCF_ADDR(0x71),
INTERNAL_CALL_PREEMPT_BY_HIGH_PRIO_APN(0x72),
EMM_ACCESS_BARRED(0x73),
EMERGENCY_IFACE_ONLY(0x74),
IFACE_MISMATCH(0x75),
COMPANION_IFACE_IN_USE(0x76),
IP_ADDRESS_MISMATCH(0x77),
IFACE_AND_POL_FAMILY_MISMATCH(0x78),
EMM_ACCESS_BARRED_INFINITE_RETRY(0x79),
AUTH_FAILURE_ON_EMERGENCY_CALL(0x7A),
// OEM sepecific error codes. To be used by OEMs when they don't
// want to reveal error code which would be replaced by ERROR_UNSPECIFIED
OEM_DCFAILCAUSE_1(0x1001),
OEM_DCFAILCAUSE_2(0x1002),
OEM_DCFAILCAUSE_3(0x1003),
OEM_DCFAILCAUSE_4(0x1004),
OEM_DCFAILCAUSE_5(0x1005),
OEM_DCFAILCAUSE_6(0x1006),
OEM_DCFAILCAUSE_7(0x1007),
OEM_DCFAILCAUSE_8(0x1008),
OEM_DCFAILCAUSE_9(0x1009),
OEM_DCFAILCAUSE_10(0x100A),
OEM_DCFAILCAUSE_11(0x100B),
OEM_DCFAILCAUSE_12(0x100C),
OEM_DCFAILCAUSE_13(0x100D),
OEM_DCFAILCAUSE_14(0x100E),
OEM_DCFAILCAUSE_15(0x100F),
// Local errors generated by Vendor RIL
// specified in ril.h
REGISTRATION_FAIL(-1),
GPRS_REGISTRATION_FAIL(-2),
SIGNAL_LOST(-3), /* no retry */
PREF_RADIO_TECH_CHANGED(-4),
RADIO_POWER_OFF(-5), /* no retry */
TETHERED_CALL_ACTIVE(-6), /* no retry */
ERROR_UNSPECIFIED(0xFFFF),
// Errors generated by the Framework
// specified here
UNKNOWN(0x10000),
RADIO_NOT_AVAILABLE(0x10001), /* no retry */
UNACCEPTABLE_NETWORK_PARAMETER(0x10002), /* no retry */
CONNECTION_TO_DATACONNECTIONAC_BROKEN(0x10003),
LOST_CONNECTION(0x10004),
RESET_BY_FRAMEWORK(0x10005);
private final int mErrorCode;
private static final HashMap<Integer, DcFailCause> sErrorCodeToFailCauseMap;
static {
sErrorCodeToFailCauseMap = new HashMap<Integer, DcFailCause>();
for (DcFailCause fc : values()) {
sErrorCodeToFailCauseMap.put(fc.getErrorCode(), fc);
}
}
/**
* Map of subId -> set of data call setup permanent failure for the carrier.
*/
private static final HashMap<Integer, HashSet<DcFailCause>> sPermanentFailureCache =
new HashMap<>();
DcFailCause(int errorCode) {
mErrorCode = errorCode;
}
public int getErrorCode() {
return mErrorCode;
}
/**
* Returns whether or not the radio has failed and also needs to be restarted.
* By default, we do not restart radio on REGULAR_DEACTIVATION.
*
* @param context device context
* @param subId subscription id
* @return true if the radio has failed and the carrier requres restart, otherwise false
*/
public boolean isRestartRadioFail(Context context, int subId) {
if (this == REGULAR_DEACTIVATION) {
CarrierConfigManager configManager = (CarrierConfigManager)
context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
if (configManager != null) {
PersistableBundle b = configManager.getConfigForSubId(subId);
if (b != null) {
return b.getBoolean(CarrierConfigManager.
KEY_RESTART_RADIO_ON_PDP_FAIL_REGULAR_DEACTIVATION_BOOL);
}
}
}
return false;
}
public boolean isPermanentFailure(Context context, int subId) {
synchronized (sPermanentFailureCache) {
HashSet<DcFailCause> permanentFailureSet = sPermanentFailureCache.get(subId);
// In case of cache miss, we need to look up the settings from carrier config.
if (permanentFailureSet == null) {
// Retrieve the permanent failure from carrier config
CarrierConfigManager configManager = (CarrierConfigManager)
context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
if (configManager != null) {
PersistableBundle b = configManager.getConfigForSubId(subId);
if (b != null) {
String[] permanentFailureStrings = b.getStringArray(CarrierConfigManager.
KEY_CARRIER_DATA_CALL_PERMANENT_FAILURE_STRINGS);
if (permanentFailureStrings != null) {
permanentFailureSet = new HashSet<>();
for (String failure : permanentFailureStrings) {
permanentFailureSet.add(DcFailCause.valueOf(failure));
}
}
}
}
// If we are not able to find the configuration from carrier config, use the default
// ones.
if (permanentFailureSet == null) {
permanentFailureSet = new HashSet<DcFailCause>() {
{
add(OPERATOR_BARRED);
add(MISSING_UNKNOWN_APN);
add(UNKNOWN_PDP_ADDRESS_TYPE);
add(USER_AUTHENTICATION);
add(ACTIVATION_REJECT_GGSN);
add(SERVICE_OPTION_NOT_SUPPORTED);
add(SERVICE_OPTION_NOT_SUBSCRIBED);
add(NSAPI_IN_USE);
add(ONLY_IPV4_ALLOWED);
add(ONLY_IPV6_ALLOWED);
add(PROTOCOL_ERRORS);
add(RADIO_POWER_OFF);
add(TETHERED_CALL_ACTIVE);
add(RADIO_NOT_AVAILABLE);
add(UNACCEPTABLE_NETWORK_PARAMETER);
add(SIGNAL_LOST);
}
};
}
sPermanentFailureCache.put(subId, permanentFailureSet);
}
return permanentFailureSet.contains(this);
}
}
public boolean isEventLoggable() {
return (this == OPERATOR_BARRED) || (this == INSUFFICIENT_RESOURCES) ||
(this == UNKNOWN_PDP_ADDRESS_TYPE) || (this == USER_AUTHENTICATION) ||
(this == ACTIVATION_REJECT_GGSN) || (this == ACTIVATION_REJECT_UNSPECIFIED) ||
(this == SERVICE_OPTION_NOT_SUBSCRIBED) ||
(this == SERVICE_OPTION_NOT_SUPPORTED) ||
(this == SERVICE_OPTION_OUT_OF_ORDER) || (this == NSAPI_IN_USE) ||
(this == ONLY_IPV4_ALLOWED) || (this == ONLY_IPV6_ALLOWED) ||
(this == PROTOCOL_ERRORS) || (this == SIGNAL_LOST) ||
(this == RADIO_POWER_OFF) || (this == TETHERED_CALL_ACTIVE) ||
(this == UNACCEPTABLE_NETWORK_PARAMETER);
}
public static DcFailCause fromInt(int errorCode) {
DcFailCause fc = sErrorCodeToFailCauseMap.get(errorCode);
if (fc == null) {
fc = UNKNOWN;
}
return fc;
}
}