MTKevent事件机制总结.docx
- 文档编号:30037128
- 上传时间:2023-08-04
- 格式:DOCX
- 页数:26
- 大小:25.13KB
MTKevent事件机制总结.docx
《MTKevent事件机制总结.docx》由会员分享,可在线阅读,更多相关《MTKevent事件机制总结.docx(26页珍藏版)》请在冰豆网上搜索。
MTKevent事件机制总结
MTKMMIevent小结1
在MTKMMI里面有各种event,最常见的有跟交互相关的按键event,触摸屏event。
跟各种具体事件比如电话event,短信event,电量event,信号量event,timerevent等等。
MTK都有相应的处理方式,跟交互相关的按键(KeyBrd.c)和触摸屏(TouchScreen.c)各有一套自己的机子,timerevent已经在MTKtimer小结3介绍过,还有一套机制就是处理各种其他事件,它主要分为普通事件和interruptevent,interruptevent主要用于需要弹出的对话框的event。
MTKMMIevent小结2
今天主要看分析,常用事件机制。
做过MTK开发的人应该知道:
要接受MTKL4层的消息,用一个注册函数SetProtocolEventHandler,注册一个event的处理函数。
比如短信,电话,电池电量,信号量等等都是通过这个函数来注册消息。
当L4层处理完封装事件后,就会把这个event发送到MMItask里来(消息发送可以看MTKtask小结5),然后MMItask通过这个event机制,找到相应的处理函数,进行处理。
实现这种机制,也是考虑到灵活性和扩张性。
如果都在MMItask里面,用switchcase来处理,那就很疯狂了,长度不说,写个应用,定义个消息,都要去改MMItask,所以这个机制实现虽然比较简单,但是还是很有必要的。
昨天也说到,这个机制的event主要有两种,普通event和intrruptevent(中断事件),这些主要是一些需要中断当前应用的事件(主要是看那些弹出框),比如电话,有些应用需要提前处理这个消息,还有些应用需要在这个事件处理完毕后处理。
还是看代码吧
在MMItask最后,会调用函数ProtocolEventHandler,这个函数就是找到相应event的相应处理函数(平台不一样,可能实际的函数名字有些区别,但是流程基本上一样的,我这里被#define到mmi_frm_execute_current_protocol_handler)
注意:
event的处理函数使用SetProtocolEventHandler来注册。
//MsgStruct是具体事件的消息体
voidmmi_frm_execute_current_protocol_handler(U16eventID,void*MsgStruct,intmod_src,void*peerBuf)
{
U16count=0;
PsExtPeerFuncPtrcurrFuncPtr=NULL;
U8interrup_result=MMI_FALSE;/*Falsenothandleinterrupt,Truewillhandle*/
MMI_BOOLquery_result=MMI_FALSE,execute_result=MMI_FALSE;
interrupt_event_hdlrint_func=NULL,post_int_func=NULL;
mmi_frm_int_event_typecurrent_frm_int_event;
idx=mmi_frm_search_event();
{
//遍历protocolEventHandler查找是否有event注册了回调函数
//虽然这个方法感觉比较笨,就一个数组,实际上对速度没有什么影响
for(count=0;count { if(protocolEventHandler[count].eventID==eventID) { //找到处理函数 currFuncPtr=(PsExtPeerFuncPtr)protocolEventHandler[count].entryFuncPtr; //这个地方时,一个优化 //处理的事情就是把刚才现在处理的eventid往前移动一个单位 //这是考虑到程序的局部性原理,这个优化还是很有必要的 if(count>0) { protocolEventHandler[count].eventID=protocolEventHandler[count-1].eventID; protocolEventHandler[count].entryFuncPtr=protocolEventHandler[count-1].entryFuncPtr; protocolEventHandler[count-1].eventID=eventID; protocolEventHandler[count-1].entryFuncPtr=(PsFuncPtr)currFuncPtr; } break; } } } //这个就是查找是否是中断事件 current_frm_int_event=mmi_frm_interrupt_event_converter(eventID,MsgStruct); if(current_frm_int_event>0) { //查看该中断事件是否有注册提前处理函数 query_result=mmi_frm_query_interrupt_event_information(current_frm_int_event,&int_func,&post_int_func); } //如果有调用该函数 if(query_result&&int_func) { /*Newinterruptionmechanism*/ execute_result=(*int_func)(current_frm_int_event); } //根据event相应的回调函数以及前面处理的结果,来决定是否处理该事件 //要注意的是,如果interrput提前处理函数返回true,那么这里就不会执行 if((currFuncPtr)&&(! interrup_result)&&(! execute_result)) { (*currFuncPtr)(MsgStruct,mod_src,peerBuf); } else { MMI_TRACE(MMI_FW_TRC_G1_FRM,MMI_FRM_INFO_EVENT_EXECURPTO_NO_HDLR,eventID); } //interruptevent最后处理函数 if(query_result&&post_int_func) { execute_result=(*post_int_func)(current_frm_int_event); } } 看完这个,其实觉得挺简单的,对吧。 就是一个数组,数组里关联了eventid和对应的处理函数。 还有就是增加了一种intrruptevent。 可以注册这种event的pre_handlerandpost_handler。 这样如果需要,可以提前做处理或者不响应该事件。 MTKMMIevent小结3 昨天大概的说了下,普通event的执行过程。 中间还有几个函数没有介绍,这里简单介绍一下 //这个函数就是简单把L4c的interrupt消息,转换成MMI层interrupt的消息 staticmmi_frm_int_event_typemmi_frm_interrupt_event_converter(U16event_id,void*msg) { mmi_frm_int_event_typefrm_interrupt_event=0; switch(event_id) { //GPIO消息 casePRT_EQ_GPIO_DETECT_IND: { mmi_eq_gpio_detect_ind_struct*gpio_detect_ind=(mmi_eq_gpio_detect_ind_struct*)msg; switch(gpio_detect_ind->gpio_device) { //翻盖关闭 caseEXT_DEV_CLAM_CLOSE: { frm_interrupt_event=MMI_FRM_INT_CLAM_CLOSE; break; } //翻盖打开 caseEXT_DEV_CLAM_OPEN: { frm_interrupt_event=MMI_FRM_INT_CLAM_OPEN; break; } //耳机插入拔出 caseEXT_DEV_EARPHONE: { if(gpio_detect_ind->on_off==1) { frm_interrupt_event=MMI_FRM_INT_EARPHONE_PLUG_IN; } else { frm_interrupt_event=MMI_FRM_INT_EARPHONE_PLUG_OUT; } break; } } break; } //充电信息, casePRT_BATTERY_STATUS_IND: { mmi_eq_battery_status_ind_struct*battery_status_ind=(mmi_eq_battery_status_ind_struct*)msg; frm_interrupt_event=mmi_frm_get_frm_int_event_macro( battery_status_ind->battery_status, mmi_frm_int_event_battery_table, sizeof(mmi_frm_int_event_battery_table)/sizeof(mmi_frm_int_event_battery_table[0])); /*Forlowbatteryindication*/ if(battery_status_ind->battery_status==PMIC_VBAT_STATUS) { if(battery_status_ind->battery_voltage==BATTERY_LOW_WARNING) { frm_interrupt_event=MMI_FRM_INT_BATTERY_LOW_WARNING; } elseif(battery_status_ind->battery_voltage==BATTERY_LOW_TX_PROHIBIT) { frm_interrupt_event=MMI_FRM_INT_BATTERY_LOW_TX_PROHIBIT; } } break; } caseMSG_ID_TIMER_EXPIRY: caseMSG_ID_MMI_EQ_POWER_ON_IND: caseMSG_ID_MMI_EQ_KEYPAD_DETECT_IND: { break; } default: { //其他interruptevent,主要是弹出框相关,短信报告等等 frm_interrupt_event=mmi_frm_get_frm_int_event_macro( event_id, mmi_frm_int_event_convert_table, sizeof(mmi_frm_int_event_convert_table)/sizeof(mmi_frm_int_event_convert_table[0])); break; } } returnfrm_interrupt_event; } 这个函数就是把L4C的消息转换到MMI的消息,然后通过mmi_frm_query_interrupt_event_information这个函数去查找,是否有相应的注册。 这个函数比较简单,就是数组里去比较。 还有一个常用的函数是SetProtocolEventHandler,也就是注册一个消息的回调函数。 具体也没有什么可说的,无非就是循环查找是否有这个event。 1,如果有,看func是否为空,为空表示去掉这个event的注册,不为空,就直接修改这个event的func(定时器到时时所要实现的功能函数) 2,没有,就增加一个event。 这里注意,由一个小小的优化,就是判断,event数组的最后是否为无效的event,如果无效,那么减少总注册event的个数。 这个样可以减少循环查询的次数。 MTKMMIevent小结4 今天打算说说keyevent。 MTK的keyenvent管理其实跟MTK(MMIevent小结2)说的protocolevent机制也差不了多少,简单来说,就是app通过注册某一个key的回调函数,当这个key事件产生时,该机制就去找到相应的回调函数,进行回调。 先说说key的event有哪些: 1keydown按键按下KEY_EVENT_DOWN 2keyup按键弹起KEY_EVENT_UP 3keylongpress按键长按KEY_LONG_PRESS。 默认好像是长按1.5记不清楚了,可以自己设置,函数Kbd_SetLongPressTime,不过除非必不得已,不要去随便修改,可能会引起其他应用出问题,要修改,也要先获得当前值,退出应用时设置回原来的值。 4keyrepeat按键按下一直不放,发送该消息KEY_REPEAT。 举个简单例子,pc上当输入时,如果长按a键,那么回不停的增加a,这个就是repeat动作。 这个的时间好像是0.5s,也就是按住键0.5s之后,每隔0.5s,就会发送一个repeat消息。 设置函数Kbd_SetRepeatTime还有两个不常用的KEY_HALF_PRESS_DOWN和KEY_HALF_PRESS_UP,也就是说的2step可以。 先讲一下按键的处理流程。 当按键被按键之后,MMItask会收到MSG_ID_MMI_EQ_KEYPAD_DETECT_IND这个消息,在系统初始化的时候,已经注册了这个消息的处理函数mmi_frm_key_handle。 也就是说mmi_frm_key_handle是处理按键过程的函数。 这个函数mmi_frm_key_handle收到这个消息后,会通过该消息带的函数,去取当前发生的按键事件(实际这个函数就是一个按键缓存队列里去第一个,用一个按键缓存队列,可以防止按键大量的丢失,可以起到同步驱动和MMI层,驱动产生按键事件很快而MMI有可能比较慢,可以简单的理解为生产者和消费者的关系,跑题了)。 取到当前按键后,看当前是否可以进行操作,比如是否有触摸笔按下等等。 MTKMMIevent小结5 昨天说了一下keyevent的基本情况,今天直接从代码开始吧 先看执行keyevent函数mmi_frm_key_handle voidmmi_frm_key_handle(void*paraBuff) { kbd_datak; U32msg_count; mmi_eq_keypad_detect_ind_struct*p; //判断参数是否为空 //在初始化时,系统就注册了MSG_ID_MMI_EQ_KEYPAD_DETECT_IND的回调函数为mmi_frm_key_handle //当收到这个消息时,表示有按键事件要处理, //这个paraBuff是keyTask传过来的参数,里面的内容是获取按键信息的函数指针 if(paraBuff! =NULL) { drv_get_key_funcnew_key_ptr; p=(mmi_eq_keypad_detect_ind_struct*)paraBuff; new_key_ptr=(drv_get_key_func)(p->func); //判断是否是新的函数指针,如果是的话,需要进行一些清理工作 if(new_key_ptr! =keypad_ptr) { //新的函数指针,则进行清理,并且判断是否有按键需要处理 if(! mmi_kbd_process_keyptr_change((void*)new_key_ptr)) { return; } //清理按键事件缓存buffer ClearKeyEvents(); keypad_ptr=new_key_ptr; } } //通过while (1)来不停的从按键缓存里获取按键信息 //当然这里不会无限死循环,后面会进行相应处理 while (1) { //1)判读是否是挂起,2)是否key需要处理 if((g_mmi_suspend_key_flag==MMI_FALSE)&&keypad_ptr&&((*(keypad_ptr))(&k)==MMI_TRUE)) { if(k.Keydata[0]! =KEY_INVALID) { #ifdefined(__MMI_TOUCH_SCREEN__)||defined(__MMI_HANDWRITING_PAD__) kal_boolis_pen_enabled,is_pen_down; //获得触摸屏状态 mmi_pen_get_state(&is_pen_enabled,&is_pen_down); #endif/*defined(__MMI_TOUCH_SCREEN__)||defined(__MMI_HANDWRITING_PAD__)*/ #ifdefined(__MMI_TOUCH_SCREEN__)||defined(__MMI_HANDWRITING_PAD__) //如果触摸屏按下,那么保存状态 if(is_pen_down&&(k.Keyevent==WM_KEYPRESS)) { U16KeyMapIndex; //不允许按键处理 is_allow_key_action=MMI_FALSE; //把驱动的按键和MMI按键进行转换 KeyMapIndex=mmi_frm_get_idx_from_device_key_code(k.Keydata[0]); if(nKeyPadStatus[KeyMapIndex]==KEY_EVENT_UP) { KEYBRD_MESSAGEKeyBrdMsg; KeyBrdMsg.nKeyCode=nKeyPadMap[KeyMapIndex].nMMIKeyCode; if(mmi_frm_is_2step_keyCode(KeyBrdMsg.nKeyCode)) { nKeyPadStatus[KeyMapIndex]=KEY_HALF_PRESS_DOWN; pressKey=HALF_DOWN_STATUS; key_is_pressing_count++; } else { nKeyPadStatus[KeyMapIndex]=KEY_EVENT_DOWN; pressKey=FULL_DOWN_STATUS; key_is_pressing_count++; } } } else #endif/*defined(__MMI_TOUCH_SCREEN__)||defined(__MMI_HANDWRITING_PAD__)*/ //如果按键是弹起,那么还原原来按键状态,也就是弹起状态 if((k.Keyevent==WM_KEYRELEASE)&&(is_allow_key_action==MMI_FALSE)) { #ifdefined(__MMI_TOUCH_SCREEN__)||defined(__MMI_HANDWRITING_PAD__) /*ResetallowkeyflagandUpdatekeystatusevenifpenisdown*/ U16KeyMapIndex; KeyMapIndex=mmi_frm_get_idx_from_device_key_code(k.Keydata[0]); if((nKeyPadStatus[KeyMapIndex]==KEY_EVENT_DOWN) ||(nKeyPadStatus[KeyMapIndex]==KEY_HALF_PRESS_DOWN) ||(nKeyPadStatus[KeyMapIndex]==KEY_LONG_PRESS) ||(nKeyPadStatus[KeyMapIndex]==KEY_REPEAT)) { nKeyPadStatus[KeyMapIndex]=KEY_EVENT_UP; key_is_pressing_count--; } prevKeyMapIndex=prevKeyMapIndex; #endif/*defined(__MMI_TOUCH_SCREEN__)||defined(__MMI_HANDWRITING_PAD__)*/ is_allow_key_action=MMI_TRUE; } //按键是否可以处理 if(is_allow_key_action==MMI_TRUE) { if(((k.Keyevent==WM_KEYPRESS)&&(mmi_kbd_get_key_is_pressing_count()==0)) ||k.Keyevent==DRV_WM_KEYLONGPRESS||k.Keyevent==DRV_WM_KEYREPEATED||k.Keyevent==DRV_WM_KEYFULLPRESS) { #ifdefined(__MMI_TOUCH_SCREEN__)||defined(__MMI_HANDWRITING_PAD__) //关闭触摸屏 mmi_pen_disable(); #endif } //真正处理按键事件 mmi_frm_convert_proces
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- MTKevent 事件 机制 总结