声明:以下阐述皆基于L及之后的版本
一、MTK平台的两种添加紧急号码的方法:
1.紧急式呼叫:
紧急号码在XML文件中配置,文件的路径为:
..\vendor\mediatek\proprietary\external\EccList\
EccList文件夹中会包含:
ecc_list.xml ----普通紧急号码文件、
cdma_ecc_list.xml ---- CDMA紧急号码文件
以及与运营商有关的
ecc_list_OP01.xml、
ecc_list_OP09.xml、
ecc_list_OP18.xml
等对应文件,由OPTR_SPEC_SEG_DEF控制OPxx。此外还包括一个EccList.mk。
实际运行中根据EccList.mk文件定义来匹配相应的XML文件作为判断是否为紧急号码的来源。如
MTK_C2K_SUPPORT=yes,
表示支持CDMA制式,需加入cdma_ecc_list.xml。
另外,匹配的XML文件最终放置于android文件系统中system/etc目录下。
所有XML文件内容定义方法相同,下面是ecc_list.xml文件中的内容:

以紧急式添加的紧急号码,拨号时AP会下ATDEXXX;给modem。modem处理ATDE命令时,将号码直接作为紧急号码,给网络发送紧急呼叫的请求,所以以紧急式呼叫的方式添加紧急号码时modem不需要修改。2.非紧急式呼叫:
以非紧急式呼叫的方式添加紧急号码时,modem需要同步修改,修改的文件路径为:
../modem//custom/modem/common/custom_ecc.c
紧急号码需在以下数组中同步配置:
const kal_uint16 ecc_default_num[ ][ECC_CUSTOM_DEFAULT_ECC_LENGTH + 1] =
{
{0x0031, 0x0031, 0x0032, 0x0000, 1}, /* 112 */
{0x0039, 0x0031, 0x0031, 0x0000, 1}, /* 911 */
……
}
const kal_uint16 ecc_3gpp_num[ ][ECC_CUSTOM_DEFAULT_ECC_LENGTH + 1] =
{
{0x0031, 0x0031, 0x0032, 0x0000, 1}, /* 112 */
{0x0039, 0x0031, 0x0031, 0x0000, 1}, /* 911 */
……
};
数组中每项含义,举例:112
0x0031, 0x0031, 0x0032: 将ASCII转换为十进制后就是1,1,2;
0x0000:Category属性值;
1:Condition属性值;
以非紧急式添加的紧急号码,拨号时AP会下ATDXXX;给modem。modem处理ATD命令会先判断号码是否为紧急号码,即与定义的ecc_default_num等去匹配,匹配成功时modem会认为是紧急号码,并给网络发送紧急呼叫的请求,否则给网络发送的是正常呼叫的请求。
*说明:
1)添加号码请注意Condition的配置,根据需求来选择对应的值。
0:表示无卡时当紧急号码;
1:表示始终当紧急号码;
2:表示界面上显示成紧急拨号,但实际以普通方式拨出。
2)Category属性的设置与语音台选择有关,只有在实际拨打紧急号码的时候会将此号码配置的Category属性发送到Modem。国内默认都是'0’,国外根据实际情况选择,如韩国在解析紧急号码时需要解析Category属性,依据Category将emergency call转交对应的服务台。
是否要在modem匹配Category,可以在modem客制化配置。具体如下:
custom\modem\common\ps\custom_l4_utility.c
kal_bool custom_fill_ecc_category(){
return KAL_FALSE; //or KAL_TRUE
}
根据以往项目开发经验,客户要求客制化紧急号码时一般都以紧急式配置紧急号码,无需修改MODEM。
二、紧急号码在AP上的处理流程
在PhoneNumberUtils.java中对ecc_list.xml等配置文件做了解析,解析方法为:
private static void parseEccList();
由静态代码块中调用,如下:
static {
……
mCustomizedEccList = new ArrayList();
sCdmaCustomizedEccList = new ArrayList();
parseEccList();
mHashMapForNetworkEccCategory = new HashMap();
}
解析后便可根据mCustomizedEccList、sCdmaCustomizedEccList来判断是否为紧急号码。如:
isSpecialEmergencyNumber ---- Condition为2的识别
isEmergencyNumberExt ---- Condition为0或1的识别
PhoneNumberUtils类为工具类,提供了很多用于判断紧急号码的接口方法,关系如下:

在拨号流程中紧急拨号的处理使用了isEmergencyNumber、isSpecialEmergencyNumber。
如果是GSM制式,在GsmCallTracker类的dial方法中;
如果是CDMA或IMS制式,则在CdmaCallTracker或ImsPhoneCallTracker类的dial方法中;
关键代码如下:
synchronized Connection dial (String dialString, int clirMode, UUSInfo uusInfo, Bundle intentExtras)
throws CallStateException {
......
if (mPendingMO.getAddress() == null || mPendingMO.getAddress().length() == 0
|| mPendingMO.getAddress().indexOf(PhoneNumberUtils.WILD) >= 0) {
......
} else {
// Always unmute when initiating a new call
setMute(false);
/// M: CC015: CRSS special handling @{
if (!mWaitingForHoldRequest.isWaiting()) {
/// M: CC010: Add RIL interface @{
if (PhoneNumberUtils.isEmergencyNumber(dialString)
&& !PhoneNumberUtils.isSpecialEmergencyNumber(dialString)) {
int serviceCategory = PhoneNumberUtils.getServiceCategoryFromEcc(dialString);
mCi.setEccServiceCategory(serviceCategory);//Category属性传递
mCi.emergencyDial(mPendingMO.getAddress(), clirMode, uusInfo,
obtainCompleteMessage(EVENT_DIAL_CALL_RESULT));
/// @}
} else {
mCi.dial(mPendingMO.getAddress(), clirMode, uusInfo,
obtainCompleteMessage(EVENT_DIAL_CALL_RESULT));
}
} else {
mWaitingForHoldRequest.set(mPendingMO.getAddress(), clirMode, uusInfo);
}
/// @}
}
......
}
mCi为RILJ对象,它向RILC发送拨号请求,RILC进行相关处理,关键代码如下:
void requestDial(void *data, size_t datalen, RIL_Token t, int isEmergency) {
....
if (isEmergency) {
/* If an incoming call exists(+CRING is not received yet), hang it up before dial ECC */
if ((setupCpiData[0] != NULL) && isRecvECPI0) {
LOGD("To hang up incoming call(+CRING is not received yet) before dialing ECC!");
asprintf(&cmd, "AT+CHLD=1%s", setupCpiData[0]);
isRecvECPI0 = false;
int i;
for (i = 0; i < 9; i++) {
free(setupCpiData[i]);
setupCpiData[i] = NULL;
}
at_send_command(cmd, NULL, CC_CHANNEL_CTX);
free(cmd);
sleep(1);
}
asprintf(&cmd, "ATDE%s%s;", clir, p_dial->address);
} else {
// BEGIN mtk03923 [20111004][ALPS00077405]
// CC operation will fail when dialing number exceed 40 character due to modem capability limitation.
if (strlen(p_dial->address) > 40) {
LOGE("strlen(%s)=%d exceeds 40 character\n", p_dial->address, strlen(p_dial->address));
if (IMS_isRilRequestFromIms(t)) {
IMS_RIL_onRequestComplete(t, RIL_E_CANCELLED, NULL, 0);
} else {
RIL_onRequestComplete(t, RIL_E_CANCELLED, NULL, 0);
}
at_response_free(p_response);
// [ALPS00251057][Call]It didn't pop FDN dialog when dial an invalid number
// But this is not related to FDN issue, it returned to AP since number is too long.
// mtk04070, 2012.03.12
bUseLocalCallFailCause = 1;
dialLastError = 28; /* Refer to CallFailCause.java - INVALID_NUMBER_FORMAT */
return;
}
// END mtk03923 [20111004][ALPS00077405]
asprintf(&cmd, "ATD%s%s;", clir, p_dial->address);
}
ret = at_send_command(cmd, &p_response, CC_CHANNEL_CTX);
......
}
可知,最后以AT命令形式发往MODEM进行处理。
三、其它影响因素
紧急号码配置还有其它途径,如系统属性:cdma.ril.ecclist、
cdma.ril.ecclist、ril.ecclist、ril.ecclist等。
另外,国内版本支持CTA,需根据属性ro.mtk_cta_set的值配置120、122,由
ProjectConfig.mk中MTK_CTA_SET变量来决定该属性值。
关于紧急号码的相关介绍,可见FAQ02892、FAQ11774等。