MTK event 事件机制总结
- 格式:doc
- 大小:122.00 KB
- 文档页数:16
event原理Event原理事件(Event)是计算机科学中的一个重要概念,它是指在计算机系统中的某个特定时刻发生的事情或者动作。
事件可以是用户的输入、系统的响应、传感器的检测等等。
在计算机编程中,我们经常使用事件来触发特定的逻辑处理。
本文将介绍事件的原理和应用。
一、事件的原理1. 事件驱动模型事件驱动模型是指计算机程序的运行方式,它通过监听和响应事件来控制程序的执行流程。
在事件驱动模型中,程序会一直等待事件的发生,当事件发生时,程序会执行相应的处理逻辑。
事件驱动模型的核心是事件循环(Event Loop),它是一个不断循环的过程,用于监听和分发事件。
2. 事件类型事件可以分为不同的类型,常见的事件类型包括鼠标事件、键盘事件、网络事件等。
每种事件类型都有对应的事件处理器,用于处理该类型的事件。
例如,鼠标事件包括鼠标移动、点击、滚动等,键盘事件包括按键按下、释放等。
3. 事件处理器事件处理器是用于处理特定类型事件的代码块。
当事件发生时,系统会调用对应的事件处理器来执行相应的逻辑。
事件处理器可以是预定义的函数,也可以是开发者自定义的函数。
开发者可以根据自己的需求,编写相应的事件处理器来响应事件。
4. 事件监听事件监听是指程序通过注册监听器来监听特定的事件。
当被监听的事件发生时,系统会通知所有注册了监听器的对象。
监听器可以是系统内置的监听器,也可以是开发者自定义的监听器。
通过事件监听,程序可以实时获取事件的发生,并进行相应的处理。
5. 事件触发事件触发是指通过人为或外部条件的变化来主动触发事件。
例如,用户点击按钮时,会触发鼠标点击事件;传感器检测到温度变化时,会触发温度变化事件。
事件触发可以通过调用特定的函数或者改变某些属性来实现。
二、事件的应用1. 图形界面编程在图形界面编程中,事件被广泛应用。
用户的输入操作,如鼠标点击、键盘输入等,都会触发相应的事件。
程序通过监听这些事件,并执行相应的处理逻辑,来实现与用户的交互。
MTK task 小结1MTK 的基本执行单元是task,从操作系统的角度来理解,task 有些像线程而不是进程,进程之间的地址空间是相互隔离的,说白点就是进程之间的全局变量是不相互干扰的。
而线程之间则是用同一个地址空间,MTK的task之间的地址空间也是共同的,也就是说在MTK 编程里,定义了一个全局变量,那么在任何一个task里面都能引用,(这里只是举个例子,在实际编程过程中最好不要用全局变量,实在没有办法避开,那么全局变量也要分模块化,进行封装)。
所以说,MTK 的task 更像线程,MTK 用的是实时操作系统nucleus,是非抢占式操作系统,也就是当高优先级的task 在运行时,低优先级的task是得不到运行时间的,除非等高优先级的task 因为种种原因挂起。
MTK 还有一个跟task 想关的概念叫module,它跟task 之间的关系是:一个task 可以对应多个module。
task 主要表示是一个执行单元,module 主要是用于传递消息,在MTK 中,消息传递是module 为单位src_mod – > des_mod,而不是以task为单位。
MTK task 小结2虽然MTK手机,是feature phone(功能机),不像symbian 6 那样可以同时运行多个应用。
但是MTK还是由许多task组成。
平时MTK的后台播放MP3就是由一个task 完成的。
具体以后分析。
现在来看看MTK 最主要的task,MMI task,MTK的应用程序都是在该task里面运行,它有一整套开发MTK应用的framework。
先来看创建MMI task的函数kal_bool mmi_create(comptask_handler_struct **handle){/*----------------------------------------------------------------*//* Local Variables *//*----------------------------------------------------------------*/static comptask_handler_struct mmi_handler_info ={MMI_task, /* task entry function */MMI_Init, /* task initialization function */NULL,NULL, /* task reset handler */NULL, /* task termination handler */};/*----------------------------------------------------------------*//* Code Body *//*----------------------------------------------------------------*/*handle = &mmi_handler_info;return KAL_TRUE;}这个函数的结构,是MTK 创建task的基本结构,系统初始化时,会调用该函数。
MTK平台屏幕切换机制探索--group机制(11A版本)熟悉了几个模块的代码流程以后,发现屏幕创建并没有想像中的简单,每个程序似乎都要在创建自己的屏幕之前先创建一个群,随后又进入这个群后,这才开始自己屏幕的创建,为什么要这么多此一举呢,为了研究屏幕的运作流程?我用MODIS追踪了屏幕的创建过程。
首先,介绍下两个根节点,一个是屏幕根节点ROOT,所有的有效屏幕都是它的子孙节点,还一个是scenario_dangle,用来暂存刚创建或马上要销毁的屏幕节点。
然后屏幕节点分为group节点和screen节点。
group节点用来管理它旗下的screen节点,它本身并不产生实际意义上的屏幕,screen节点可以理解为我们所见到的屏幕。
其中ROOT下面的叶子节点必须得是screen节点。
如图1所示,其中,ROOT节点下面的8101节点是开机最早创建的一个group节点,它旗下有四个screen节点,其中8105节点就是选择sim卡的界面,而8108则是选择sim卡进入待机界面前的动画绘制界面,8102节点比较奇怪,它本身好像没什么效果,不知道是不是为了保证叶子节点是screen节点才创建的。
group节点和screen节点的创建过程也不太一样,我简要概括一下两者的创建和销毁流程:1.group节点:典型的函数:mmi_frm_group_createmmi_frm_group_entermmi_frm_group_close(1) 创建节点:a. 检查scenario_dangle中是否存在此idb. 检查parent节点中是否存在此idc. 若没有,则创建节点(分配内存)并赋予parent的id(但parent中未加入此节点)d. add_node(scenario_dangle, new_node):将节点插到scenario_dangle的tail中,以我跟踪的情况,每次都是在图1中1327号节点的右边(2) 移动节点a. 从scenario_dangle中获取此id的nodeb. 将此node从scenario_dangle中删除(不是free掉,因为没释放资源),然后会作检查,如果node没有parent,它会被销毁,free_node,释放资源。
mtkaee抓log原理嵌入式设备是一种电子系统,通常被用于控制、监测和操作其他设备。
在开发和维护嵌入式设备时,经常需要抓取并分析设备的日志信息,以便识别和解决问题。
MTK AEE(Android Error Exception)是联发科(MediaTek)提供的一种用于抓取设备日志的工具。
在本文中,我们将详细介绍MTK AEE抓取日志的原理和相关概念。
MTKAEE工具是由MTK平台团队开发的,旨在帮助开发人员快速识别和解决设备问题。
它通过收集设备的异常信息、错误消息和其他关键日志数据,提供给开发者进行分析。
MTKAEE工具的原理可以归纳为以下几个关键步骤:1.异常捕获:MTKAEE工具通过监控设备的运行状态,捕获系统崩溃、应用程序崩溃或其他异常事件。
当异常事件发生时,MTKAEE工具会自动触发异常捕获机制。
2.数据收集:一旦异常事件被捕获,MTKAEE工具开始收集相关的日志数据。
这些数据包括设备状态信息、堆栈跟踪、内存转储、日志文件和其他可能与异常事件相关的数据。
3.日志处理:MTKAEE工具将收集到的日志数据进行处理和分析。
它可以解析日志文件、提取关键信息,并生成相应的报告。
这些报告可以为开发人员提供有关异常事件的详细信息,以帮助他们快速定位和解决问题。
4.日志传输:MTKAEE工具通常支持将收集到的日志数据传输到开发人员的计算机或服务器。
这使得开发人员可以在更大的屏幕上查看和分析日志数据,从而更容易识别和解决问题。
MTKAEE工具中的关键概念包括:1.异常类型:MTKAEE工具可以捕获各种异常类型,包括操作系统错误、驱动程序故障、应用程序崩溃等。
不同类型的异常可能需要不同的分析和解决方法。
2.异常级别:MTKAEE工具可以为每个异常事件指定一个级别,用于指示异常的严重程度。
这有助于开发人员优先解决较高级别的异常,以确保设备的稳定性和性能。
3.资源消耗:MTKAEE工具在捕获和处理日志时会消耗设备的资源,包括内存、存储和处理器功率。
MTK平台开发总结(全)声明:前阶段进行了近两个月的MTK平台上层开发,由于缺乏技术支持,对于整个平台的认识都是通过简略的文档和浅薄的经验摸索出来的。
其间整理了一些文档。
由于联发科提供的PDF全部是英文,有些名词难以翻译准确,只能凭单方理解和嵌入式开发的词汇习惯进行意译,还请谅解。
系列文章均出自原创,肤浅可笑之处,望海涵。
(一)窗体的重画通过观察可以发现,每个窗体模板都调用这样一个函数:dm_redraw_category_scree n()。
这个函数便是显示窗体的函数。
它内部的实现是这样的:获得该窗体所包含的组件及它们的属性,再根据组件的类型和属性,调用不同的接口,逐一绘制各组件。
详细流程如下图所示:由上面的流程可见,无论是窗体所包含的组件,还是组件的属性,都是根据模板ID获取的。
那么现在摆在面前的有两个问题:一、模板ID是如何传递到这个函数中的;二、模板ID和窗体组件、组件的属性,是如何关联到一起的。
我们逐一解决这两个问题。
一、模板ID是如何传递到这个函数中的模板ID,是Sho wCateg ory..Screen()过程中,所显示的界面的编号,千万不要与EntryNe wScree n(scrID,…) 函数中传入的窗口ID相混淆。
它们以―MMI_‖为前缀,被定义在枚举型结构MMI_CATEGORY_ID_L IST中,又通过结构体d m_data_struct和它的全局结构体变量g_dm_data,在应用程序中被广泛使用。
先看看结构体dm_data_struct的定义:typedef struct{S32 s32ScrId;S32 s32Cat Id;S32 s32fl ags;}其中,s32ScrId是当前窗口ID,也就是我们使用EntryNe wScree n()时传入的那个参数;而s32Cat Id才是模板ID;最后的flag,是模板需要显示软键盘、清屏等动作时,所置的标志变量,它在上面提到的那个dm_redraw_category_scree n()函数中被判断。
event机制
event机制是一种在软件系统中处理事件的机制,事件是系统
中发生的某种特定的行为或状态变化。
通过event机制,系统
能够检测和响应特定的事件,例如用户操作、网络消息、传感器输入等。
在event机制中,事件的发生者称为事件源(event source),
事件的接收者称为事件处理器(event handler)。
事件源可以
是软件组件的一部分,例如图形用户界面中的按钮、键盘输入等;也可以是外部设备或其他应用程序等。
事件处理器是负责处理事件的代码块或函数。
事件机制的基本工作流程如下:
1. 事件的发生者(事件源)产生一个事件,通常以函数或方法的形式。
2. 事件源将事件传递给事件机制的管理者,例如事件队列或事件循环。
3. 事件管理者根据事件的类型和优先级,将事件分发给对应的事件处理器。
4. 事件处理器执行特定的代码逻辑,以响应事件。
5. 事件处理器处理完事件后,可以触发其他事件或更新系统状态。
通过使用event机制,系统能够实现高度灵活和可扩展的事件
驱动编程模型。
不同的事件处理器可以注册到同一个事件源上,以处理不同的事件类型。
同时,系统可以进行事件过滤、优先
级调整等操作,以满足不同的业务需求。
常见的应用场景包括图形用户界面编程、网络编程、服务器端编程等。
例如,图形用户界面中的按钮点击事件、鼠标移动事件等都可以通过event机制进行响应和处理。
MTK MMI event 小结 1在MTK MMI 里面有各种event,最常见的有跟交互相关的按键event,触摸屏event;跟各种具体事件比如电话event,短信event,电量event,信号量event,timer event等等;MTK 都有相应的处理方式,跟交互相关的按键和触摸屏各有一套自己的机子,timer event 已经在MTK timer 小结 3 介绍过,还有一套机制就是处理各种其他事件,它主要分为普通事件和interrupt event,interrupt event 主要用于需要弹出的对话框的event;M T K MMI event 小结 2今天主要看分析,常用事件机制;做过MTK开发的人应该知道:要接受MTK L4 层的消息,用一个注册函数SetProtocolEventHandler,注册一个event 的处理函数;比如短信,电话,电池电量,信号量等等都是通过这个函数来注册消息;当L4 层处理完封装事件后,就会把这个event 发送到MMI task 里来消息发送可以看MTK task 小结 5 ,然后MMI task 通过这个event 机制,找到相应的处理函数,进行处理;实现这种机制,也是考虑到灵活性和扩张性;如果都在MMI task 里面,用switch case 来处理,那就很疯狂了,长度不说,写个应用,定义个消息,都要去改MMI task,所以这个机制实现虽然比较简单,但是还是很有必要的;昨天也说到,这个机制的event 主要有两种,普通event 和intrrupt event中断事件,这些主要是一些需要中断当前应用的事件主要是看那些弹出框,比如电话,有些应用需要提前处理这个消息,还有些应用需要在这个事件处理完毕后处理;还是看代码吧在MMI task 最后,会调用函数ProtocolEventHandler,这个函数就是找到相应event 的相应处理函数平台不一样,可能实际的函数名字有些区别,但是流程基本上一样的,我这里被define 到mmi_frm_execute_current_protocol_handler注意:event的处理函数使用SetProtocolEventHandler来注册;ventID == eventID{ntryFuncPtr;ventID = protocolEventHandlercount - 1.eventID;protocolEventHandlercount.entryFuncPtr = protocolEventHandlercount - 1.entryFuncPtr;protocolEventHandlercount - 1.eventID = eventID;protocolEventHandlercount - 1.entryFuncPtr = PsFuncPtr currFuncPtr;}break;}}}4c4CMMIKeyCode;if mmi_frm_is_2step_keyCode{nKeyPadStatusKeyMapIndex = KEY_HALF_PRESS_DOWN;pressKey = HALF_DOWN_STATUS;key_is_pressing_count++;}else{nKeyPadStatusKeyMapIndex = KEY_EVENT_DOWN;pressKey = FULL_DOWN_STATUS;key_is_pressing_count++;}}}elseendif / defined__MMI_TOUCH_SCREEN__ ||defined__MMI_HANDWRITING_PAD__ /MMIKeyCode;if mmi_frm_is_2step_keyCode{nKeyPadStatusKeyMapIndex = KEY_HALF_PRESS_DOWN;key_is_pressing_count++;= KEY_HALF_PRESS_DOWN;}else{nKeyPadStatusKeyMapIndex = KEY_EVENT_DOWN; / same with KEY_FULL_PRESS_DOWN /key_is_pressing_count++;= KEY_EVENT_DOWN;}MMIKeyCode;KeyEventHandlerKEYBRD_MESSAGE & KeyBrdMsg;}else{/ Ignore the event /}}/ ++Robin, modified by Max Chen /else if MsgType == DRV_WM_KEYLONGPRESS{if nKeyPadStatusKeyMapIndex == KEY_EVENT_DOWN{KEYBRD_MESSAGE KeyBrdMsg;nKeyPadStatusKeyMapIndex = KEY_LONG_PRESS;= KEY_LONG_PRESS;= nKeyPadMapKeyMapIndex.nMMIKeyCode;KeyEventHandlerKEYBRD_MESSAGE & KeyBrdMsg;}else{/ Ignore the event /}}else if MsgType == DRV_WM_KEYREPEATED{if nKeyPadStatusKeyMapIndex == KEY_LONG_PRESS || nKeyPadStatusKeyMapIndex == KEY_REPEAT{KEYBRD_MESSAGE KeyBrdMsg;nKeyPadStatusKeyMapIndex = KEY_REPEA T;= KEY_REPEA T;= nKeyPadMapKeyMapIndex.nMMIKeyCode;KeyEventHandlerKEYBRD_MESSAGE & KeyBrdMsg;}else{/ Ignore the event /}}else if MsgType == DRV_WM_KEYFULLPRESS{/Only in two-stage key will have KEY_FULL_PRESS_DOWN, and it followed after KEY_HALF_PRESS_DOWN/if nKeyPadStatusKeyMapIndex == KEY_HALF_PRESS_DOWN{KEYBRD_MESSAGE KeyBrdMsg;nKeyPadStatusKeyMapIndex = KEY_EVENT_DOWN;= KEY_EVENT_DOWN;= nKeyPadMapKeyMapIndex.nMMIKeyCode;KeyEventHandlerstruct KEYBRD_MESSAGE&KeyBrdMsg;}else{/ Ignore the event /}}else if MsgType == DRV_WM_ENABLE_TWOKEY_DETECTION || MsgType ==DRV_WM_ENABLE_THREEKEY_DETECTION ||MsgType == DRV_WM_DISABLE_MULTIKEY_DETECTION {/ Ignore the event /}else{MMI_TRACEMMI_FW_TRC_G6_FRM_DETAIL,MMI_FRM_ERROR_PROC_KEYEVENT_HDLR;MMI_ASSERT0;}}KeyEventHandler 函数主要判断是否要真的处理该事件,可以看成是一个按键事件的拦截,比如应用切换过程中,需要一个切换动画,而这个动画工程中,需要处理忽略这些按键;就需要特殊的处理;static void KeyEventHandlerKEYBRD_MESSAGE eventKey{MMI_BOOL is_hdlr_enabled = MMI_TRUE;kbd_pre_func{is_hdlr_enabled = eventKey;}if frm_p->currKeyType == KEY_EVENT_DOWN &&isInCall && GetWapCallPresent &&IsBitReset, frm_p->currKeyType{RegisterEndKeyHandlerInCall;}先看一下初始化函数:mmi_pen_initvoid mmi_pen_initvoid{g_pen_initialized = KAL_TRUE;// 看到这两个函数指针,是不是感觉很熟悉对,就是跟key 一样,前置处理和后置处理函数// 这个看多了,不用细看代码就能猜到了;= NULL;= NULL;// 设置手写输入法的区域,手写输入法在触摸屏这里需要特殊处理;mmi_pen_stop_capture_strokes;// 设置触摸屏采样时间间隔,参数一是在普通状态下,采样时间间隔,参数二是手写输入法状态下,采样时间间隔mmi_pen_config_sampling_periodMMI_PEN_SAMPLING_PERIOD_1,MMI_PEN_SAMPLING_PERIOD_2;// 设置超时时间间隔mmi_pen_config_timeout_periodMMI_PEN_LONGTAP_TIME,MMI_PEN_REPEA T_TIME, MMI_PEN_STROKE_LONGTAP_TIME;// 设置move 的间距,也就是两个点之间多少个pixel 算move 事件;mmi_pen_config_move_offsetMMI_PEN_SKIP_MOVE_OFFSET,MMI_PEN_SKIP_STROKE_MOVE_OFFSET,MMI_PEN_SKIP_LONGTAP_OFFSET,MMI_PEN_SKIP_STROKE_LONGTAP_OFFSET;// 设置drv 的回调函数,也就是当产生事件时,会回调这个函数touch_panel_cb_registrationmmi_pen_touch_panel_sendilm, NULL;// 设置MMI 层消息MSG_ID_TP_EVENT_IND 的处理函数SetProtocolEventHandlermmi_pen_touch_panel_event_ind, MSG_ID_TP_EVENT_IND;}在驱动drv 这一层,触摸屏有一个task-- MOD_TP_TASK,在处理事件,MOD_TP_TASK 会回调用touch_panel_cb_registration 注册的函数,当pen event 事件产生了,这个pen event 缓存里取,这里注册的是:mmi_pen_touch_panel_sendilm 函数,这个函数就是简单的向MMI task 发送一个消息MSG_ID_TP_EVENT_IND,让MMI task 来处理;这里这么做的原因也很简单,drv 的task 优先级是很高的,要处理的东西也很多,所以希望回调函数能很快处理完这个事情发送一个消息很快,这里可以想一下pc 上的中断,这两者差不多;当然中断还有更多其他原因,比如内核态和用户态等等,需要回调函数尽可能快处理,发送消息到消息队列扯远了;;;;还有一点需要说明的是,现在触摸屏的手机越来越普遍,那么该善触摸屏的体验是非常重要的,可惜的是MTK 的又不是多点触摸,处理起来很费劲;这个时候就需要充分利用好这里的几个设置,采样时间间隔,以及move 事件距离;需要时,让自己app可以捕获尽可能多的点,然后自己进行计算,来判断用户行为;这对改善体验很有帮助;当然这个也是比较耗电的,不需要时,一定要设置回普通状态;。
event原理Event原理Event(事件)是计算机领域中常用的概念,用于描述系统中发生的特定事情或动作。
事件通常由用户触发,例如点击鼠标、按下键盘等,也可以是系统自动触发的,例如定时器超时、网络连接建立等。
事件的原理是计算机系统通过监听和处理事件来实现对用户操作的响应。
事件的原理主要包括事件的产生、传递和处理三个过程。
首先,事件的产生是指用户或系统触发了特定的动作,例如点击按钮、滚动鼠标等。
这些动作会被输入设备捕获并转化为相应的事件信号。
事件的传递是指事件信号从输入设备传递到操作系统或应用程序。
操作系统负责管理和分发事件信号,根据事件的类型和优先级将其分发给相应的应用程序。
事件传递过程中可能涉及到多个层级的处理,例如操作系统、桌面环境和应用程序等。
事件的处理是指应用程序根据接收到的事件信号作出相应的响应。
应用程序会注册感兴趣的事件类型,并提供相应的事件处理函数。
当事件信号传递到应用程序时,系统会调用相应的事件处理函数来处理该事件。
事件处理函数可以执行各种操作,例如更新界面、响应用户操作等。
在事件的处理过程中,事件驱动是一个重要的概念。
事件驱动是指系统的行为由事件的发生而触发,而不是按照固定的顺序执行。
事件驱动的特点是异步性和非阻塞性,应用程序可以同时处理多个事件,提高系统的并发性和响应速度。
事件的原理在图形用户界面(GUI)中得到广泛应用。
用户通过鼠标和键盘等输入设备与计算机交互,操作系统和应用程序通过监听和处理事件来实现对用户操作的响应。
例如,用户点击按钮会触发按钮的点击事件,应用程序可以在按钮的事件处理函数中执行相应的操作。
除了GUI,事件的原理在其他领域也有应用。
例如,在网络编程中,事件驱动模型可以用于处理网络连接和数据收发等操作。
当网络连接建立或数据到达时,系统会触发相应的事件,应用程序可以通过监听和处理这些事件来实现对网络操作的控制。
总结起来,事件的原理是计算机系统通过监听和处理事件来实现对用户操作的响应。
MTK定时器消息处理机制一、基本概念及Neclus内核定时器初始化expires:指定定时器到期的时间,这个时间被表示成自系统启动以来的时钟滴答计数(也即时钟节拍数)。
当一个定时器的expires值小于或等于jiffies变量时,我们就说这个定时器已经超时或到期了。
在初始化一个定时器后,通常把它的expires域设置成当前expires变量的当前值加上某个时间间隔值(以时钟滴答次数计。
typedef struct timertable{U16 timer_id[SIMULTANEOUS_TIMER_NUM];eventid event_id[SIMULTANEOUS_TIMER_NUM];oslTimerFuncPtr callback_func[SIMULTANEOUS_TIMER_NUM];struct timertable *next;} TIMERTABLE;typedef lcd_dll_node *eventid;struct lcd_dll_node {void *data;lcd_dll_node *prev;lcd_dll_node *next;};(1)timer_id:定时器id最多同时12个。
(2)双向链表元素event_id:用来将多个定时器调度动作连接成一条双向循环队列。
(3)函数指针callback_func:指向一个可执行函数。
当定时器到期时,内核就执行function所指定的函数,产生expires 消息。
//L4 init the timervoid L4InitTimer(void){TIMERTABLE *p;TIMERTABLE *pp;p = g_timer_table.next;pp = NULL;do{if (p != NULL){pp = p->next;OslMfree(p);}p = pp;} while (p != NULL);memset(&g_timer_table, 0, sizeof(TIMERTABLE));g_timer_table_size = SIMULTANEOUS_TIMER_NUM;g_timer_table_used = 0;get_clocktime_callback_func = NULL;set_clocktime_callback_func = NULL;stack_init_timer (&base_timer1, "MMI_Base_Timer1", MOD_MMI);event_scheduler1_ptr = new_evshed(&base_timer1,L4StartBaseTimer, L4StopBaseTimer,0 , kal_evshed_get_mem, kal_evshed_free_mem, 0);stack_init_timer (&base_timer2, "MMI_Base_Timer2", MOD_MMI);event_scheduler2_ptr = new_evshed(&base_timer2,L4StartBaseTimer, L4StopBaseTimer,0, kal_evshed_get_mem, kal_evshed_free_mem, 255);}typedef struct stack_timer_struct_t {module_type dest_mod_id;kal_timerid kal_timer_id;kal_uint16 timer_indx;stack_timer_status_type timer_status;kal_uint8 invalid_time_out_count;} stack_timer_struct;见以下代码:(MMI Timer Event Scheduler)//MMI定时器动作调度函数void EvshedMMITimerHandler(void *dataPtr){stack_timer_struct* stack_timer_ptr;stack_timer_ptr = (stack_timer_struct*)dataPtr;if (stack_timer_ptr == &base_timer1){if (stack_is_time_out_valid(&base_timer1)){evshed_timer_handler(event_scheduler1_ptr);}stack_process_time_out(&base_timer1);}else if (stack_timer_ptr == &base_timer2){if (stack_is_time_out_valid(&base_timer2)){evshed_timer_handler(event_scheduler2_ptr);}stack_process_time_out(&base_timer2);}}上面讲的是如何对消息进行处理,那么设置定时器后这消息是如何发出去呢?这个过程还没有讲。
MTK MMI event 小结1在MTK MMI 里面有各种event,最常见的有跟交互相关的按键event,触摸屏event。
跟各种具体事件比如电话event,短信event,电量event,信号量event,timer event等等。
MTK 都有相应的处理方式,跟交互相关的按键(KeyBrd.c)和触摸屏(TouchScreen.c) 各有一套自己的机子,timer event 已经在MTK timer 小结 3 介绍过,还有一套机制就是处理各种其他事件,它主要分为普通事件和interrupt event,interrupt event 主要用于需要弹出的对话框的event。
M T K MMI event 小结2今天主要看分析,常用事件机制。
做过MTK开发的童鞋应该知道要接受MTK L4 层的消息,用一个注册函数Set Protocol Event Handler,注册一个event 的处理函数。
比如短信,电话,电池电量,信号量等等都是通过这个函数来注册消息。
当L4 层处理完封装事件后,就会把这个event 发送到MMI task 里来(消息发送可以看MTK task 小结5 ),然后MMI task 通过这个event 机制,找到相应的处理函数,进行处理。
实现这种机制,也是考虑到零活性和扩张性。
如果都在MMI task 里面,用switch case 来处理,那就很疯狂了,长度不说,写个应用,定义个消息,都要去改MMI task,所以这个机制实现虽然比较简单,但是还是很有必要的。
昨天也说到,这个机制的event 主要有两种,普通event 和intrrupt event(中断事件),这些主要是一些需要中断当前应用的事件(主要是看那些弹出框),比如电话,有些应用需要提前处理这个消息,还有些应用需要在这个事件处理完毕后处理。
还是看代码吧在MMI task 最后,会调用函数ProtocolEventHandler,这个函数就是找到相应event 的相应处理函数(平台不一样,可能实际的函数名字有些区别,但是流程基本上一样的,我这里被#define 到mmi_frm_execute_current_protocol_handler)注意:event的处理函数使用Set Protocol Event Handler来注册。
// MsgStruct 是具体事件的消息体void mmi_frm_execute_current_protocol_handler(U16 eventID, void *MsgStruct, int mod_src, void *peerBuf){U16 count = 0;PsExtPeerFuncPtr currFuncPtr = NULL;U8 interrup_result = MMI_FALSE; /* False not handle interrupt, True will handle */MMI_BOOL query_result = MMI_FALSE, execute_result = MMI_FALSE;interrupt_event_hdlr int_func = NULL, post_int_func = NULL;mmi_frm_int_event_type current_frm_int_event;idx = mmi_frm_search_event();{// 遍历protocolEventHandler 查找是否有event 注册了回调函数// 虽然这个方法感觉比较笨,就一个数组,实际上对速度没有什么影响for (count = 0; count < maxProtocolEvent; count++){if (protocolEventHandler[count].eventID == eventID){//找到处理函数currFuncPtr = (PsExtPeerFuncPtr)protocolEventHandler[count].entryFuncPtr;// 这个地方时,一个优化// 处理的事情就是把刚才现在处理的event id 往前移动一个单位// 这是考虑到程序的局部性原理,这个优化还是很有必要的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){/* New interruption mechanism */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);}// interrupt event 最后处理函数if (query_result && post_int_func){execute_result = (*post_int_func)(current_frm_int_event);}}看完这个,其实觉得挺简单的,对吧。
就是一个数组,数组里关联了event id 和对应的处理函数。
还有就是增加了一种intrrupt event。
可以注册这种event 的pre_handler and post_handler。
这样如果需要,可以提前做处理或者不响应该事件。
M T K MMI event 小结3昨天大概的说了下,普通event 的执行过程。
中间还有几个函数没有介绍,这里简单介绍一下// 这个函数就是简单把L4c 的interrupt消息,转换成MMI 层interrupt的消息static mmi_frm_int_event_type mmi_frm_interrupt_event_converter(U16 event_id, void *msg) {mmi_frm_int_event_type frm_interrupt_event = 0;switch (event_id){// GPIO 消息case PRT_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){// 翻盖关闭case EXT_DEV_CLAM_CLOSE:{frm_interrupt_event = MMI_FRM_INT_CLAM_CLOSE;break;}// 翻盖打开case EXT_DEV_CLAM_OPEN:{frm_interrupt_event = MMI_FRM_INT_CLAM_OPEN;break;}// 耳机插入拔出case EXT_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;}// 充电信息,case PRT_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]));/* For low battery indication */if (battery_status_ind->battery_status == PMIC_VBAT_STATUS){if (battery_status_ind->battery_voltage == BATTERY_LOW_W ARNING){frm_interrupt_event = MMI_FRM_INT_BATTERY_LOW_WARNING;}else if (battery_status_ind->battery_voltage ==BA TTERY_LOW_TX_PROHIBIT){frm_interrupt_event =MMI_FRM_INT_BA TTERY_LOW_TX_PROHIBIT;}}break;}case MSG_ID_TIMER_EXPIRY:case MSG_ID_MMI_EQ_POWER_ON_IND:case MSG_ID_MMI_EQ_KEYPAD_DETECT_IND:{break;}default:{//其他interrupt event,主要是弹出框相关,短信报告等等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;}}return frm_interrupt_event;}这个函数就是把L4C 的消息转换到MMI 的消息,然后通过mmi_frm_query_interrupt_event_information 这个函数去查找,是否有相应的注册。