如何拦截短消息

来源:互联网 发布:政务大数据基因系统 编辑:程序博客网 时间:2024/06/11 03:12
1.1 拦截短信SOP(09B之前的版本) 
API原型 
void mmi_frm_sms_reg_msg_check( 
 PsExtPeerIntFuncPtr action, 
 PsFuncPtrFuncPtr callback); 
功能描述 
 通过使用该函数,可以对收到的新短信(通过action Function)作检查, 如果符合条件(返回值为TRUE), 则会(通过callback Function)把该短信相关信息传给对应的Application。该Application可以决定这个SMS是否还会被SMS Application处理到(比如把该SMS放在SMS Application的Inbox, 并显示给用户)。我们在这里称这种行为为“短信拦截”。 
 对于同一个SMS, 只能被其中一个注册的Application所拦截;当同时存在多个注册的Application时,则需要分优先级;高优先级的Application拦截到该SMS时(即其action Function的返回值为TRUE时), 低优先级的Application就没有机会可以拦截。 
 目前采用比较简单的方式,优先级是根据注册的前后顺序, 注册越靠前,优先级越高;目前在SMS Application内部,已经存在了2个拦截。 
函数参数 
action 
检查函数;检查新来的SMS是否符合某种条件,当返回值为TRUE时,则会调用callback Function. 
callback 
回调函数; 当action的返回值为TRUE时,会执行callback function; callback Function的返回值可以决定该SMS是不是还会被SMS Application处理到(比如把该SMS放在SMS Application的Inbox, 并显示给用户)。当返回值为TRUE时,则允许SMS Application处理该SMS, 为FALSE,则不会由SMS Application处理。需要注意的是,在我们平台,SMS是由L4作保存的,如果不希望拦截的SMS不被SMS Application处理,则需要删除该SMS, 否则在下次开机,该SMS还会出现在SMS Inbox。 
类型描述 
PsExtPeerIntFuncPtr 
typedef U8 (*PsExtPeerIntFuncPtr)( 
void *data, 
int withobject, 
void *content);  
data 
该SMS的Information,需要做强制转换mmi_frm_sms_deliver_msg_struct; 
withobject 
 是否有EMS Object, 即是否是EMS,而不是一般的Text SMS; TRUE表示有,FALSE为没有 
content 
该SMS的内容,内容的编码方式是由data中的dcs决定的; 如果dcs是GSM 7Bit编码,则content的编码格式为ASCII,如果是UCS2, 则content的编码格为Unicode。 
PsFuncPtrFuncPtr 
typedef U8 (*PsExtPeerIntFuncPtr)( 
void *data, 
int withobject, 
void *content);  
data 
该SMS的Information,需要做强制转换mmi_frm_sms_deliver_msg_struct; 
Withobject 
是否有EMS Object, 即是否是EMS,而不是一般的Text SMS; TRUE表示有,FALSE为没有 
content 
该SMS的内容,内容的编码方式是由data中的dcs决定的; 如果dcs是GSM 7Bit编码,则content的编码格式为ASCII,如果是UCS2, 则content的编码格为Unicode。 
mmi_frm_sms_deliver_msg_struct 
typedef struct 

 U8 fo; 
 U8 scts[7]; 
 l4c_number_struct sca_number; 
 l4c_number_struct addr_number; 
 U8 pid; 
 U8 dcs; 
 U8 ori_dcs; 
 U16 index; /* for awaited message, this is the start index */ 
 U16 dest_port; 
 U16 src_port; 
 U8 mti; 
 U8 display_type; 
#ifdef __MMI_MESSAGES_COPY__ 
 U8 storageType; 
#endif  
U32 concat_info; 
 U16 no_msg_data; 
 U8 msg_data[1]; /* for awaited message, this is the first segment data */ 
} mmi_frm_sms_deliver_msg_struct; 
fo 
SMS TPDU的First Otect,用于判断短信的类型,是否有UDH等(具体可以参见sepc23.040的9.2.2.1) 
scts 
短信中心时间戳, 短信中心收到该SMS的时间,我们在Inbox里可以看到的时间;在开UM的情况下,对于Outbox,Unsent或Draft,为发送或保存的时间。在这个Case,是收到的SMS的时间。(具体可以参见spec23.040的9.2.3.11) 
sca_number 
短信中心号码 
addr_number 
接收者号码(DA)或发送者号码(OA); 在这个Case,是发送者的号码 
pid 
Protocol Identifier,如为0x00则是SMS Application, 0x32则是Email。(具体可以参见spec23.040的9.2.3.9) 
dcs 
Content部分编码格式,具体值请参考smsal_dcs_enum 
ori_dcs 
在TPDU中的TP-DCS字段值 
index 
L4 index, 在这个Case,为第一个Segment的L4 Index. 
dest_port 
目的端口,如果该SMS为端口短信,则不为零 
src_port 
源端口,如果该SMS为端口短信,则不为零 
mti 
message type identifier, 表示该SMS的类型(参考spec23.040的9.2.3.1) 
display_type 
显示类型,具体值请参考smsal_display_type_enum  
storageType 
存储类型,具体值请参考smsal_storage_enum 
concat_info 
长短信(Concatenated SMS)的Information, 包括这个SMS多少个Segment,这个Segment的第几个等。 
2个低字节为Reference number; 
最高字节为该SMS Segment是第几个Segment; 
第三字节为该SMS的总Segment数。 
no_msg_data 
SMS content部分的字节数 
msg_data[1] 
新来的SMS的Content都会缓存在一个Buffer里, msg_data的是第一个Segment的Content缓存Buffer的Index。 
l4c_number_struct 
 typedef struct 
 { 
 kal_uint8 type; 
 kal_uint8 length; 
 kal_uint8 number[MAX_CC_ADDR_LEN]; 
 } l4c_number_struct; 
type 
号码的类型,如0x81表示国内号码,0x91表示国际号码,(通常用“+”表示)。 
length 
号码长度,number部分的长度 
number 
号码, 号码只有我们在MMI常见的号码的数字部分, 
Sample Code 
注册拦截函数 
为了保证拦截的Application优先级,需要统一在如下位置作注册,在文件
…\mcu\plutommi\mmi\messages\messagesscr\smspshandler.c中 
 void mmi_msg_set_protocol_event_handler(void) 
 { 
 …… 
 //Add your register function 
mmi_frm_sms_reg_msg_check( 
sample_check_new_sms, 
sample_capture_new_sms); 
 } 
检查函数 action 
 U8 sample_check_new_sms(void *data, int withobject, void *content) 
 { 
 mmi_frm_sms_deliver_msg_struct *msg =  
(mmi_frm_sms_deliver_msg_struct*)data; 
 //If it is an EMS 
 if (withobject) 
 { 
 return FALSE; 
 } 
 else 
 { 
 if (/* Add your check code */) 
 { 
 return TRUE; 
 } 
 else 
 { 
 return FALSE; 
 } 
 } 
 } 
回调函数callback 
static MMI_BOOL sample_is_deleting_sms; 
pBOOL sample_capture_new_sms(void *data, S8 *content) 

 mmi_frm_sms_deliver_msg_struct *inMsg =  
(mmi_frm_sms_deliver_msg_struct*) data; 
 /* Add your handle code */ 
/* If doesn't allow the user to see this sms in the SMS Inbox, delete it */ 
/* If the arrival of new sms is very frequent, the deleting request is also very frequent; But he SMS
Framework can't handle too much request in short time,so we need to stored the sms index when deleting a
sms, and delete the next one after the deleting is finished. */ 
 if (sample_is_deleting_sms == MMI_TRUE) 
 { 
 //Stored the new sms L4 index when it is deleting a sms 
 if (sample_add_sms_index(inMsg->index) == MMI_FALSE) 
 { 
 /* If add SMS index failed, increase the value  
of the MACRO SAMPLE_MAX_STORED_INDEX_NUM */ 
 MMI_ASSERT(0); 
 } 
 } 
 else 
 { 
 //If the sms is ready 
 if (mmi_frm_sms_get_sms_list_size(MMI_FRM_SMS_NOBOX) !=
MMI_FRM_SMS_INVALID_INDEX) 
 { 
 sample_delete_capture_sms_req(inMsg->index); 
 } 
 else //If the sms is not ready 
 { 
 if (sample_add_sms_index(inMsg->index) == MMI_FALSE) 
 { 
 /* If add SMS index failed, increase the value  
of the MACRO SAMPLE_MAX_STORED_INDEX_NUM */ 
 MMI_ASSERT(0); 
 } 
 //register the event which the SMS is ready 
 mmi_frm_sms_reg_interrupt_check( 
 MOD_MMI, 
 PRT_MSG_ID_MMI_SMS_READY_IND,
sample_handle_sms_ready); 
 } 
 } 
/ * If don’t want the SMS application to handle this SMS, return FALSE, else return TRUE. In this
sample code, don’t want the SMS showed in the Inbox, so return FALSE */ 
 return FALSE; 

NOTE: 
 如果不希望该SMS出现在Inbox, 被User看到,则应该删除它,否则在下次开机时 ,它还会出现在Inbox. 
 如果在短时间内收到大量的SMS,则出现在短时间内会做多次删除的操作,但是由于SMS Framework的Action Queue Size为15,即最多只能支持15个删除的Request;当删除的操作被其它的操作Suspend时,就会出现有被拦截的SMS不会被删除的情况。 
 因此对于可能出现的这种情况,处理的策略是:当在拦截到新来SMS时,如果有正在删除的SMS,则把该新来的SMS的L4 Index保存,等待正在删除的动作完成后,则删除其它保存了L4 Index的SMS. 
 如果SMS Not Ready,则不能作删除的动作,所以需要把新来的SMS的L4 Index保存;此时注册SMS Ready的Interrupt, 在SMS Ready时再作删除的动作。 
保存SMS L4 Index 
#define SAMPLE_MAX_STORED_INDEX_NUM 100 
typedef struct 

 U16 index[SAMPLE_MAX_STORED_INDEX_NUM]; 
 U16 header; 
 U16 tailer; 
 U16 total_num; 
}sample_stored_new_sms_index_struct; 
sample_stored_new_sms_index_struct *sample_stored_index; 
//Add new sms l4 index in the buffer 
static MMI_BOOL sample_add_sms_index(U16 index) 

 if (sample_stored_index == NULL) 
 { 
 sample_stored_index = OslMalloc(sizeof 
(sample_stored_new_sms_index_struct)); 
 sample_stored_index->header = 0; 
 sample_stored_index->tailer = 0; 
 sample_stored_index->total_num = 0; 
 } 
 if (sample_stored_index->total_num == SAMPLE_MAX_STORED_INDEX_NUM) 
 { 
 return MMI_FALSE; 
 } 
 sample_stored_index->index[sample_stored_index->tailer] = index; 
 sample_stored_index->tailer++; 
 sample_stored_index->total_num++; 
  
 if (sample_stored_index->tailer == SAMPLE_MAX_STORED_INDEX_NUM) 
 { 
 sample_stored_index->tailer = 0; 
 } 
  
 return MMI_TRUE; 

static U16 sample_get_next_sms_index(void) 

 U16 index = MMI_FRM_SMS_INVALID_INDEX; 
  
 if (sample_stored_index != NULL) 
 { 
 if (sample_stored_index->total_num == 0) 
 { 
 OslMfree(sample_stored_index); 
 sample_stored_index = NULL; 
 } 
 else 
 { 
 index = sample_stored_index->index 
 [sample_stored_index->header]; 
  
 sample_stored_index->header++; 
 sample_stored_index->total_num--; 
  
if (sample_stored_index->header ==
SAMPLE_MAX_STORED_INDEX_NUM) 
 { 
 sample_stored_index->header = 0; 
 } 
 } 
 } 
 return index; 

SMS Ready后的处理 
如果需要获取SMS Ready事件,需要使用下面的API注册该事件的回调函数 
 void mmi_frm_sms_reg_interrupt_check( 
module_type mod, 
U16 msgid, 
PsFuncPtrU16 callback); 
static void sample_handle_sms_ready( 
void *dummy, 
module_type mod, 
U16 result) 

 U16 index = sample_get_next_sms_index(); 
 if (index != MMI_FRM_SMS_INVALID_INDEX) 
 { 
 sample_delete_capture_sms_req(index); 
 } 

删除SMS 
void sample_delete_capture_sms_req(U16 index) 

 //Set the flag when delete 
 sample_is_deleting_sms = MMI_TRUE; 
  
 /* the typde of the capture SMS is MMI_FRM_SMS_APP_AWAITS */ 
 mmi_frm_sms_delete_sms( 
 sample_delete_capture_sms_rsp, 
 MOD_MMI, 
 MMI_FRM_SMS_APP_AWAITS, 
 index); 

void sample_delete_capture_sms_rsp( 
void *dummy, 
module_type mod, 
U16 result) 

 U16 index;  
 if (result == MMI_FRM_SMS_OK) 
 { 
 //Delete Success 
 //Add Handle Code 
 } 
 else 
 { 
 //Delete Failed 
 //Add handle Code 
 } 
 //Get next new SMS which stored  
index = sample_get_next_sms_index(); 
 //Delete next new SMS which stored 
 if (index != MMI_FRM_SMS_INVALID_INDEX) 
 { 
 sample_delete_capture_sms_req(index); 
 } 
 else 
 { 
 sample_is_deleting_sms = MMI_FALSE; 
 } 

 
 
1.2 拦截短信SOP(09B) 
09B 中将sms部分分为了UI和service两个部分,在09B之前的处理是在SMSAL层存储短信,然后传给MMI,再由MMI来处理。但是在09B中拦截短信在service部分拦截就OK。09B sms的架构图如下:
从上图中可以看到service部分中包含了Reciever,这部分就是用来处理接收短信的所有的流程的。 
当收到一条短信后会首先进入函数srv_sms_new_sms_ind,最后会进入函数srv_sms_handle_new_msg进行处理,在该函数中会针对不同类型的sms进行处理,保存sms也是在这个函数里处理的。所以拦截短信只要在这个函数里进行拦截就OK了。 
srv_sms_handle_new_msg会调用smslib_decode_pdu和smslib_get_msg_content 解析msg,解析完成后信息存储在app_lib_data中,然后使用需要的条件来判断拦截短信就OK了。 
结构体介绍如下:(可以使用这些值设定条件做判断) 
smslib_general_struct *app_lib_data 
typedef struct 

 smslib_sim_status_enum status; 
 l4_addr_bcd_struct sca; 
 smslib_tpdu_decode_struct tpdu; 
 kal_uint8 pdu_len; /* length of PDU */ 
 kal_uint8 tpdu_len; /* length of TPDU */ 
 l4c_number_struct forMMI_SCAAddr; 
 l4c_number_struct forMMI_TPAddr; 
 kal_uint16 forMMI_UserData_length; /*unit: octet*/ 
 kal_uint8 forMMI_UserData[170]; 
} smslib_general_struct; 
typedef struct 

 union 
 { 
 smslib_deliver_peer_struct deliver_tpdu; 
 smslib_submit_peer_struct submit_tpdu; 
 smslib_status_report_peer_struct report_tpdu; 
 } data; 
 smslib_mti_enum mti; 
 // 
 kal_uint8 fo; /* first octet */ 
 kal_uint8 offset; /* offset to message content */ 
 /* init address of User Data Header */ 
 kal_uint8 msg_len;/* length of user data */ 
 /* User Data Header + User Data */ 
 kal_uint8 udhl; /* for calculating offset to unpack */ 
 /* udhl + udh */ 
 smslib_concat_struct concat_info; 
 /* for decoding DCS */ 
 smslib_msg_class_enum msg_class; 
 smslib_alphabet_enum alphabet_type; 
 kal_uint8 is_compress; 
 
 smslib_msg_waiting_struct msg_wait; 
 /* User Data Header */ 
 smslib_port_struct port; 
} smslib_tpdu_decode_struct; 
typedef struct 

 kal_uint8 reply_flag; /* whether reply is sought*/ 
 kal_uint8 udh_p; /* indicates presence of 
 user data header*/ 
 kal_uint8 status_rep_flag; /* whether status reports 
 are sought*/ 
 kal_uint8 fill_bits; /* to be ignored*/ 
 kal_uint8 mms; /* more message to send*/ 
 kal_uint8 msg_type; /* sms deliver*/ 
 kal_uint8 no_orig_addr; 
 kal_uint8 orig_addr_size; /* the max size of *orig_addr in octet*/ 
 kal_uint8 *orig_addr; /* assumed to be 
 byte-packed*/ 
 kal_uint8 pid; /* to be bit-wise decoded*/ 
 kal_uint8 dcs; /* to be bit-wise decoded*/ 
 kal_uint8 scts[7]; 
 kal_uint8 user_data_len; 
 kal_uint8 no_user_data; /* 7-bit to octet */ 
 kal_uint8 user_data_size; /* the max size of *user_data in octet*/ 
 kal_uint8 *user_data; /* can have user data header also*/ 
} smslib_deliver_peer_struct; 
typedef struct 

 kal_uint8 type_of_info; 
 kal_bool need_store; 
 kal_bool is_msg_wait; 
 kal_bool is_show_num[SMSLIB_NUM_OF_MSG_WAITING_TYPE]; 
 kal_bool is_clear[SMSLIB_NUM_OF_MSG_WAITING_TYPE]; 
 kal_bool ind_flag[SMSLIB_NUM_OF_MSG_WAITING_TYPE]; 
 smslib_mwis_struct mwis; 
 kal_uint8 msp; 
  
#ifdef __SMS_R6_ENHANCED_VOICE_MAIL__ 
 smsal_evmi_struct evmi; // should free this after processing 
#endif 
} smslib_msg_waiting_struct;//waiting message ind相关 
typedef struct 

 kal_int32 dest_port; /* -1: invalid port */ 
 kal_int32 src_port; 
} smslib_port_struct; // = smsal_port_struct
原创粉丝点击