(转)MTK_面试的几个主要问题

1按键处理流程

主要简单分析一下左右软件的事件,以左软键事件为例

牵涉到的常用函数:

void SetKeyHandler( FuncPtr funcPtr, U16 keyCode, U16 keyType );

void SetLeftSoftkeyFunction( void (*f)(void), MMI_key_event_type k );

void ChangeLeftSoftkey( U16 s, U16 i );

1.   SetKeyHandler与SetLeftSoftkeyFunction

(1). SetKeyHandler

主要作用就是将需要起作用的函数的指针(funcPtr)

-->全局矩阵数组currKeyFuncPtrs[keyCode][keyType]的指定位置 ;

(2). SetLeftSoftkeyFunction

该函数内部主要流程:

Step1. call register_left_softkey_handler( )

这个函数call SetKeyHandler: 存储需要起作用的函数(left_softkey_down/left_softkey_up)

以left_softkey为例, 该函数首先首先刷新按键区域图像(redraw_softkey),

然后执行关联函数(softkey_functions[key][k]).

Step2. 在上一步里我们会发现,softkey_functions[key][k]里的函数指针没有初始化

通过 call set_left_softkey_function(f, k);

--->softkey_functions[key][k] = f;

这样,就成功的把按键按下/放开的作用函数与具体的动作关联起来了。

Step3. 最后call SetInputboxLSKFunction(f)

--->将上述函数与特定的输入(如触摸笔)关联起来。

(3). 以上两个函数的主要区别:

SetLeftSoftkeyFunction可以识别长按状态并且可以关联触摸笔操作等。

2.   ChangeLeftSoftkey

主要执行流程:

Step1. call change_left_softkey: 设置左软键图表,文字

Step2. redraw_softkey: 刷新左软键显示区域

2高亮處理機制

MTK高亮机制

1介绍:...3

2相关函数和变量列表:...3

3高亮机制说明:...5

4相关知识点说明:...7

1介绍:

本文旨在介绍MTK平台高亮机制的处理逻辑,相信能对刚入手MTK平台的同学有一定帮助,也能给平时为了项目进度和其他原因,对MTK的这些基本常识不求甚解,只能依葫芦画瓢的添加菜单和处理函数的同学一个警醒和帮助,能主动去深入了解问题和提高自己。

本人从事MTK的时间也不长,上面的话有些托大,对新手还是说得过去的。文档中有些地方不正确和清楚的,欢迎评论和讨论。

2相关函数和变量列表:

voidRegisterHighlightHandler(void(*f)(S32item_index))

注册窗口的通用高亮处理函数。

MMI_list_highlight_handler

通用高亮处理函数的全局变量指针。

voidExecuteCurrHiliteHandler(S32hiliteid)

当前高亮菜单项的通用处理函数,它会找到菜单项对应的处理函数。一般在窗口创建过程中被创建RegisterHighlightHandler(ExecuteCurrHiliteHandler)。

FuncPtrmmi_frm_get_hilite_hdlr(U16menu_id)

获取menu_id对应的菜单高亮函数,从两个函数指针数组里获取。先查找动态菜单的高亮函数指针数组,这个是在程序中动态添加的数组;如果找不到,再到静态数组里查找,这个数组是在编译过程中生成的,通常我们在res_mainmenu.c等函数里增加的菜单会被资源生成工具编译成一个静态数组。

mmi_frm_int_hilite_hdlr_table[]动态数组。

mmi_frm_const_hilite_hdlr_table[]静态数组。

currParentID

当前父窗口全局变量

voidSetHiliteHandler(U16itemid,FuncPtrhiliteFuncPtr)

设置动态高亮数组的MENUID及它相对应的处理函数,一般用在自定义的菜单项。比如在图片浏览、JAVA应用、WAP记录等不可预期菜单项数目的环境,我们不可能做静态的MENUID和处理函数,就需要用到动态的实现方式。

hintData[][]

[待确认]:这是一个动态菜单的数据缓冲,和MENUID一一对应。通俗一点说,就是菜单的显示字符串。网上有文章对此以及ConstructHintsList()理解应该有误,主要是因为代码里该函数注释说是处理静态的,应该是注释错了。引用一段描述:

3、ConstructHintsList()

ConstructsHintListforastaticmenuscreen

voidConstructHintsList(U16parentID,U8**hintArray)

{。。。。。。

(*maxHiliteInfo[hiliteItemID[i]].hintFuncPtr)(idx);//SetHintHandler注册的函数的函数在此被执行

hintArray[idx]=hintData[idx];//该语句是该函数的核心,就是将全局变量hintData[idx]数组地址

//赋给用户传过来的指针数组;至于hintData[idx]中是否有数据不

//管;hintData[idx]的数据会在调用SetHintHandler注册的函数时对其

//进行初始化;要记住SetHintHandler注册的函数在SetHiliteHandler注册的

//函数之前执行。

我认为ConstructHintsList()是创建动态菜单的,时间关系,待分析。

3高亮机制说明:

3.1使用流程

每个窗口进入后基本都有类似下面的一段程序:

。。。。。。

EntryNewScreen(EM_DEBUG_INFO_SCR,NULL,EntryEMDebugInfo,NULL);

guiBuffer=GetCurrGuiBuffer(EM_DEBUG_INFO_SCR);

nItems=GetNumOfChild(EM_DEBUG_INFO_MENUID);

GetSequenceStringIds(EM_DEBUG_INFO_MENUID,ItemList);

SetParentHandler(EM_DEBUG_INFO_MENUID);

RegisterHighlightHandler(ExecuteCurrHiliteHandler);

ShowCategory52Screen(。。。)

SetRightSoftkeyFunction(GoBackHistory,KEY_EVENT_UP);

。。。。。。

3.2分析

这是窗口建立过程的一个通用处理结构,这里简单说明一下,每个函数的具体实现和功能请阅读代码。

EntryNewScreen初始化建立一个窗口需要的变量和过程,并退出上一个窗口,清除按键处理函数等;

SetParentHandler很重要,设置当前父窗口全局变量的MENUID,用来定位到当前是在哪一个窗口,后面依据他来在菜单树中查找到高亮的菜单项的MENUID,找到菜单项的MENUID后,通过mmi_frm_get_hilite_hdlr(U16menu_id)可以找到菜单项对应的高亮函数;RegisterHighlightHandler把ExecuteCurrHiliteHandler注册成一个通用的高亮处理函数,我们只要告诉ExecuteCurrHiliteHandler当前高亮的菜单项的MENUID,它就能找到执行函数并开始执行了。到这里就应该已经基本明白了高亮机制了,弄明白了其实也很简单的^_^;

ShowCategory52Screen()只是一个窗口界面绘制函数,和事件处理逻辑没有关系。

SetRightSoftkeyFunction(GoBackHistory,KEY_EVENT_UP)等函数设置这个窗口要响应哪些按键事件,并设置好相应的处理函数。

3.3高亮函数触发过程

RegisterHighlightHandler把ExecuteCurrHiliteHandler注册成一个通用的高亮处理函数,实际上是给MMI_list_highlight_handler函数指针赋值。触发则需要调用MMI_list_highlight_handler。

由于MTK平台支持各种菜单形式,比如纯文本的菜单、带CHECKBOX的、带RADIO的、带一个图片的、带两个图片的、两行的。我们现在只对一种标准菜单进行分析,其他形式的分析方法相同。

standard_list_highlight_handler(S32item_index)里会执行注册的高亮处理函数MMI_list_highlight_handler,而standard_list_highlight_handler本身又是一个注册函数,在wgui_fixed_list_create_text_menu()里会被注册到MMI_fixed_list_menu.item_highlighted,MMI_fixed_list_menu是菜单组件的数据结构,包含有菜单组件从显示到功能处理函数的所有数据,具体每个组件怎么被显示,怎么响应功能按键就不在这里讨论了,后续我可能会写出文档,有兴趣的同学自己看代码,效果会更好。

这里简单说一下,MMI_fixed_list_menu.item_highlighted在这个组件里,会被gui_fixed_list_menu_switch_highlighted_item()函数来执行,而gui_fixed_list_menu_switch_highlighted_item()则在上下按键执行的时候被执行,比响应上按键的函数是voidfixed_list_goto_previous_item(void),它调用voidgui_fixed_list_menu_goto_previous_item(fixed_list_menu*m),而voidgui_fixed_list_menu_goto_previous_item(fixed_list_menu*m)则调用gui_fixed_list_menu_switch_highlighted_item(),整个触发过程就完成了。

关于上下按键的注册,则在wgui_fixed_list_create_text_menu()里有:

if(flag&WGUI_LIST_MENU_DISABLE_VOL_KEY)

register_fixed_list_keys_ex();

else

register_fixed_list_keys();

来注册按键事件处理函数,其实现过程很简单:

voidregister_fixed_list_keys(void)

{

SetKeyHandler(fixed_list_goto_previous_item,KEY_UP_ARROW,KEY_EVENT_DOWN);

SetKeyHandler(fixed_list_goto_next_item,KEY_DOWN_ARROW,KEY_EVENT_DOWN);

SetKeyHandler(fixed_list_goto_previous_item,KEY_VOL_UP,KEY_EVENT_DOWN);

SetKeyHandler(fixed_list_goto_next_item,KEY_VOL_DOWN,KEY_EVENT_DOWN);

}

关于如何实现按键事件的响应、按键的处理逻辑,又是一个专题了。大致包括键盘中断、去抖、键盘映射、检测、进程通信、应用部分按键处理机制等,有机会再写出文档。

4相关知识点说明:

4.1初始化相关

高亮的一些全局变量会在InitEvents()里进行初始化,在event.c文件里。这个函数在开机过程中的一个调用栈关系如下:

InitEvents();

InitEventHandlersBeforePowerOn();

voidMMI_task(oslEntryType*entry_param)

InitEvents();还会在InitFramework()中被调用,而InitFramework()会由于开机的状态不同,如USB开机、闹钟开机等,调用流程也不尽相同。具体的可参见我的另一篇应用开机流程的文档。

4.2菜单结构及查找

4.2.1菜单数数组示意

constCUSTOM_MENUmtk_nCustMenus[]={

{1,0,18,0,16,2,10933,11062,(U16*)nOrderMenuItem_0},

{2,0,3,1,0,1,26218,26085,(U16*)nOrderMenuItem_1},

{3,2,0,1,0,1,555,0,(U16*)0},

{4,2,0,1,0,1,552,0,(U16*)0},

{5,2,0,1,0,1,26173,0,(U16*)0},

{0,0,0,0,0,0,0,0,(U16*)0},

{0,0,0,0,0,0,0,0,(U16*)0},

{0,0,0,0,0,0,0,0,(U16*)0},

{0,0,0,0,0,0,0,0,(U16*)0},

{0,0,0,0,0,0,0,0,(U16*)0},

{0,0,0,0,0,0,0,0,(U16*)0},

。。。。。。。。

}

CUSTOM_MENUnCustMenus[MAX_MENU_ITEMS];

4.2.2通过父窗口MENUID及高亮INDEX找到高亮窗口MENUID

U16GetSeqItemId_Ext(U16parent_item_id,U16index)

{

U8i=0,idx=0;

U16item_id=0;

U8child_count=(U8)nCustMenus[parent_item_id-1].nNumofMenuItem;

#ifdefDEVAPP_RESOURCE

if(parent_item_id>=MENU_ID_DEVAPP_START)

{

returnDevAppGetSeqItemId_Ext(parent_item_id,index);

}

#endif

for(i=0;i<child_count;i++)

{

item_id=nCustMenus[parent_item_id-1].nOrderMenuItemId[i];

if(!mmi_frm_test_menu_item_hide(item_id))

{

if(idx==index)

{

break;

}

else

{

idx++;

}

}

}

MMI_TRACE(MMI_FW_TRC_G2_GUI,MMI_RESGEN_ALL_MENU_HIDE,parent_item_id);

returnitem_id;

}

4.2.3通过高亮窗口MENUID找到对应的高亮函数

FuncPtrmmi_frm_get_hilite_hdlr(U16menu_id)

{

U32index;

if(mmi_frm_binary_search((U32)menu_id,(mmi_frm_pair_data_struct*)mmi_frm_int_hilite_hdlr_table,

(U32)mmi_frm_int_hilite_hdlr_count,&index))

{

returnmmi_frm_int_hilite_hdlr_table[index].hilite_hdlr;

}

elseif(mmi_frm_binary_search((U32)menu_id,

(mmi_frm_pair_data_struct*)mmi_frm_const_hilite_hdlr_table,

(U32)ARRAY_COUNT(mmi_frm_const_hilite_hdlr_table),&index))

{

returnmmi_frm_const_hilite_hdlr_table[index].hilite_hdlr;

}

else

{

returnNULL;

}

}

3 MTK 內存管理

1

内存管理。平台不提供动态分配内存的方式;应用程序需要使用动态分配内存时,可以采用以下几种方式:

与系统其他模块共享内存,典型的是使用MED模块的内存;

定义一个静态数组,交给系统adm托管,然后调用kal_adm_alloc、kal_adm_free等内存操作函数实现动态内存分配;

定义一个静态数组,应用自己实现基于此数组的分配和管理,也就是实现自己的内存管理模块。

2

内存分配机制

在MTK的资料中,介绍了它的内存管理机制,有3种:ADM、Control buffer、System Memory。后两个是系统使用的,与上层应用无关。但是我对kal_system_alloc也做了初步分析。

sys_mem_ptr,其估计应该指向的是 System_Mem_Pool,       debug_mem_ptr,其估计应该指向的是 debug_Mem_Pool。       经过初步分析,kal_system_alloc就是从System_Mem_Pool做简单的加法操作,sys_mem_left_size就是 System_Mem_Pool还剩下多少。kal_system_alloc从sys_mem_ptr开始来计算要取的内存。ctrl_buf是通过 kal_system_alloc的内存,然后再通过NU_Create_Partition_Pool创建POOL。系统的一些task stack.等也都是通过kal_system_alloc来分配的。

也就是说,Control buffer、System Memory用的都是System_Mem_Pool的空间。而System_Mem_Pool可以查到,是在custom_configmem函数中配置。

ADM就完全没有使用操作系统提供的内存管理算法,是平台自创了一套。开发者,可以自己开辟一个POOL,自己在这个池用ADM提供的内存管理API完成内存的动态管理。具体的分配算法,就没有再细看,跟一些通用的内存分配算法应该一致。但是在以前调试一个问题的时候,应该是可以断定,ADM在每一个alloc node前后都加了GAP调试区,来判断是否被overwrite。

至于系统中,到底是用了多少块内存用于ADM,各块内存又是让哪些应用在共享,开发者可能更清楚。在系统中是否建立了对内存动态分配的监控机制,比如查询内存泄漏、动态内存使用效率等等。

3

少于2K 使用get_ctrl_buffer。

大于2K 使用adm

get_ctrl_buffer是在系统定义的一块区域申请空间。 这段空间被分为好多块均等大小。好像有以下几种方式:

2个 1K*2

4个 0.5K*4

6个 0.25K*8

....

申请的话,按首适应算法。这就是你所说的小块内存管理。

adm主要是你自己定义的一块全局数组比如400K.

你可以使用它的adm相关函数去动态申请释放这400K大小的区域,维护也靠你自己。

4 任務管理

任务管理。系统任务采用静态创建方式,静态配置任务优先级、栈大小、任务全局唯一ID等;不提供动态创建Task的方式;任务内部以及任务之间的通信通过内部事件队列和外部事件队列完成

Application_Initialize中的mainp函数,负责任务的创建。我们在代码中见不到任务创建的函数,只需要维护任务初始化参数数据结构。对于系统的那些task信息,都保存在sys_comp_config_tbl变量中,我们看不到。但是MTK提供给客户的custom_comp_config_tbl,客户是可以修改的,在这里用户可以定义自己的task。

关于任务,需要关心数据结构comptask_handler_struct。关于comptask_handler_struct成员的执行顺序,应该是:comp_init_func 在系统还未 schedule 即在Application_Initialize中完成,然后task schedule后执行comp_entry_func。comp_cfg_func、comp_reset_func、comp_end_func我认为无太多意义。

5 事件機制

事件机制。平台事件机制采用“注册一回调”机制,把需要处理的各个按键、触摸屏等通过系统函数注册,当有事件发生时系统调用所注册的监听者。

6 定時器消息機制

MTK定时器消息机制分析

1.   数据结构

(1). stack_timer_struct

定时器类型的信息结构( 其主要作用似乎是用以装载待发送的定时器消息数据 )

(2). TIMERTABLE

定时器队列节点结构( 其由主要元素mmi_frm_timer_type结构及链表指针两个元素组成 )

(3). event_scheduler

队列信息结构

(4). mmi_frm_timer_type

定时器信息结构

2.   L4定时器初始化

(1). 步骤

...-> 创建MMI Task -> 设置MMI Task初始化函数 -> 在该函数中调用 L4InitTimer

(2). 作用

初始化定时器队列并设置基本定时器1,2

3.   发送定时器消息

(1). 步骤

StartTimer -> L4StartTimer

(2). 两种类型的定时器

MTK中有两种类型的定时器

a. NO_ALIGNMENT

非队列式的,即要求立即执行的定时器,时间到了就自动被reset.

b. ALIGNMENT

队列式的, 即可以通过队列操作,有一定的延时容忍的定时器 .                                   y

其基本执行流程: 执行定时器 --> 超时? --> 保存timer id,event id -- timer stop || no event ?----> END ;

|               Y                                       N|

|                                                        |

----------------------------------------------------------

c. 除了触摸屏和手写,其他情况下的定时器一般都是队列式的.

(3). L4StartTimer的作用

判断将要发送的定时器ID,根据是否是队列类型传递给不同的队列结构(event_sheduler1/event_sheduler2) ;

(4). TimerExpiry

这是作为参数传递给L4StartTimer的回调函数,由于MTK做了一定的封装,因此其内部具体回调触发过程

无法得知,但根据猜测,应该是在定时时间一到,以中断的方式发出消息(MSG_ID_TIMER_EXPIRY),并将其写到

MMI的循环队列.

该函数可能是在L4CallBackTimer中调用的,L4CallBackTimer的作用如下:

a. 重置当前定时器信息结构(mmi_frm_timer_type) ;

b. 执行定时器到点后的执行函数(TimerExpiry) ;

c. 讲Timer消息写到MMI循环队列中 .

4.   与StartTimer对应的StopTimer

(1). 具体实现通过调用L4StopTimer操作.

(2). 作用: 找出指定要停止的定时器ID在队列中的位置,然后使用evshed_cancel_event将指定定时器节点从队列

中删除.

5.   定时器消息的处理

(1). 步骤

...-> 创建MMI Task -> 设置MMI Task入口函数 -> 调用 EvshedMMITimerHandler

(2). evshed_timer_handler( ) -> 处理具体的定时器事件

(转)MTK_面试的几个主要问题 必看相关推荐

  1. 上周面试回来后写的Java面试总结,想进BAT必看

    上周陪同之前一起工作的同事去面试(乔治,小袁,鹏飞(面试人)),第一站是去深圳,第二站上海,第三站杭州.面试什么公司我在这里就不多说了,你们知道是一线公司就行.其实本来真的没打算写这篇文章,主要是自己 ...

  2. 百度、阿里等大厂面试技巧总结,Java工程师必看!

    要说面试大厂,最难的地方就是技术面,尤其是有3-7次面试流程的公司,让求职者很难在面试官不断地询问中坚持完成面试流程,如果基础不好,也没有掌握面试技巧,那么淘汰的几率就会大很多. 所以在面试前,我们一 ...

  3. 面试的技巧!【精品必看】转自猫扑

    先发个关于薪酬的... 面试人: 你目前的工资是多少? 提示:记住! 你的收入不仅包括你的工资, 还包括奖金.津贴及其它福利,将各项福利换算成 现金,并计算在你的收入中.求职者:我的基本工资是年薪32 ...

  4. 想跳槽涨薪的必看!2021年百度Java面试真题,跳槽大厂必看!

    前言 MyBatis是一个支持普通SQL查询.存储过程和高级映射的优秀持久层框架.MyBatis 去掉了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以使用简单的XML ...

  5. python开发工程师面试题-超实用面试必看,Python工程师面试题

    原标题:超实用面试必看,Python工程师面试题 面试是公司挑选职工的一种重要方法.它给公司和应招者提供了进行双向交流的机会,能使公司和应招者之间相互了解,从而双方都可更准确做出聘用与否.受聘与否的决 ...

  6. 最新iOS面试必看题视频教程(附大神简历要素)

    2019独角兽企业重金招聘Python工程师标准>>> 本文是由尚学堂iOS学院总结的ios开发者在求职时会遇到的一些面试题 ,并通过实际代码演练将课程详尽的讲解出来,希望对学习io ...

  7. 面试必看:java面试考点精讲视频教程

    面试必看:java面试考点精讲视频教程 Java作为目前比较火的计算机语言之一,连续几年蝉联最受程序员欢迎的计算机语言榜首,因此每年新入职Java程序员也数不胜数.很多java程序员在学成之后,会面临 ...

  8. 网络工程师面试题(面试必看)(3)

    作者简介:一名云计算网络运维人员.每天分享网络与运维的技术与干货.   座右铭:低头赶路,敬事如仪 个人主页:网络豆的主页​​​​​​ 前言 本系列将会提供网络工程师面试题,由多位专家整合出本系列面试 ...

  9. 联发科射频工程师题目_【MTK联发科技射频工程师面试】意外接到联发科人力资...-看准网...

    我是计算机科学方向的本科生.25 号周四联发科 MediaTek 来学校进行提前批招聘了,我就拉着室友一起去了,我们之前刷了之前的笔试题,然后刚好遇到了几道完全一样的几道题目:1. 计算二进制数字位中 ...

最新文章

  1. zabbix Server 4.0 监控TCP的12种状态
  2. 关于bind1st和bind2nd
  3. echarts实时更新数据_虎牙为S10拼了8.0年度更新!随时回放实时数据,还能养柴犬...
  4. 中国银屑病患者中银屑病关节炎的患病率和特征
  5. MVC 3.0错误 HTTP 404您正在查找的资源(或者它的一个依赖项)可能已被移除,或其名称已更改,或暂时不可用。请检查以下 URL 并确保其拼写正确。...
  6. vue-cli 使用Mint-UI
  7. jQuery常用操作部分总结
  8. 阶段5 3.微服务项目【学成在线】_day01 搭建环境 CMS服务端开发_12-MongoDb入门-基础概念...
  9. mac终端支持git
  10. ensp 双机热备 配置_华为交换机VRRP配置教程(一)
  11. linux命令安装tongweb教程,【中间件】TongWeb安装
  12. Java版进销存ERP管理系统源码
  13. 利用US-100超声波传感器测距的核心代码
  14. 网络知识:水晶头网线和网线插座接法制作过程介绍
  15. 优秀IT项目经理的基本要求
  16. [Vulkan教程]绘制一个三角形/呈现/交换链(Swip chain)
  17. 【计算机组成原理】学了计组,CPU执行时间你肯定会算了吧
  18. 朱广权迎手语新搭档?百度智能云AI手语主播正式上岗
  19. 何恺明 matlab,[论文复现]何恺明博士CVPR2009去雾算法(1)
  20. 图像处理之Matlab图像读取

热门文章

  1. BZOJ 2301 Problem b
  2. Shell脚本中的并发(转)
  3. split和join和pop和remove用法
  4. 关于PHP会话:session和cookie
  5. 【Head First Java 读书笔记】(四)对象的行为
  6. 错误处理和调试2 - C++快速入门31
  7. 几款主流的 Python IDE
  8. java异常中的finally(一)
  9. java.lang unsupported classversion解决方法
  10. 解决vue2+vue-cli3项目ie兼容问题