android 紧急号码,MTK平台紧急号码实现

声明:以下阐述皆基于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文件中的内容:

11813302_2016070915254900842H77GNQCQU9MHYUN7H.jpg

以紧急式添加的紧急号码,拨号时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类为工具类,提供了很多用于判断紧急号码的接口方法,关系如下:

11813302_201607091525490116X9AOUOBJMBIV26JBDQ.jpg

在拨号流程中紧急拨号的处理使用了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等。