• 985.43 KB
  • 2022-04-22 11:37:46 发布

软件工程毕业论文设计-基于MTK平台移动终端应用层软件的设计与实现.doc

  • 81页
  • 当前文档由用户上传发布,收益归属用户
  1. 1、本文档共5页,可阅读全部内容。
  2. 2、本文档内容版权归属内容提供方,所产生的收益全部归内容提供方所有。如果您对本文有版权争议,可选择认领,认领后既往收益都归您。
  3. 3、本文档由用户上传,本站不保证质量和数量令人满意,可能有诸多瑕疵,付费之前,请仔细先通过免费阅读内容等途径辨别内容交易风险。如存在严重挂羊头卖狗肉之情形,可联系本站下载客服投诉处理。
  4. 文档侵权举报电话:19940600175。
'软件工程XXXX企业指导教师姓名职称学校指导教师姓名职称XX工程领域作者姓名二〇XX年三月提交论文日期XX教授ApplicationsoftwareBasedonMTKplatformDesignandImplementationofMobileTerminal应用层软件的设计与实现基于MTK平台移动终端题(中、英文)目代号分类号学号密级UDC编号 摘要目前,手机已成为最广范围内使用的便携式电话终端。很多国家也成功地将本土品牌手机推向了国际市场。在手机的研发过程中,人机交互接口(MMI)给进行移动通信的人与手机提供了交往的界面,它的设计优劣直接影响了手机销售市场的占有率,本文对人机界面的设计与实现进行了研究和探讨。本文首先介绍了手机发展现状和课题选题由来,阐明了课题的现实意义和主要任务。基于手机结构和嵌入式操作系统介绍了本项目的软件开发平台——MTK平台,并详细分析了该平台MMI层软件结构。其中以手机应用层开发中的典型模块——通讯录应用为例,先进行了系统需求分析和方案设计。然后具体实现了模块的各功能与所有界面,并完成了应用间交互的相关功能,后期根据编写的测试用例进行了黑盒测试。最终,样机通过了软、硬件测试,验证了其设计的正确性和可行性,并成功投入市场。关键字:手机人机交互接口(MMI)MTK黑盒测试 AbstractNowadays,handsethasbecomeacellularphoneterminalinthemostwidelyusedfield.Agreatmanycountriessucceededindesigningvarioushandsetslabelledbytheirownbrandininternationalmarket.TheMan-Machine-Interface(MMI)providessuchaninterfacethatbringstheconveniencetobothhumanandhandsetinthehandsetprojects.Andtheadvantagesornotofdesigncouldmakeanimportantinfluenceonthemarketshareofmobileterminalproducts.ThethesismakestherelatedR&Dtodesignandachieveafriendlyinterface.Thethesisfirstintroducesthepresentsituationandbackgroundofhandset,andclarifiesthesignificanceofthetopicandmaintask.Onthebasisofthearchitectureofhandsetandtheembeddedsystem,introducesthesoftwaredevelopmentplatformofthisproject,MTKplatform,andthesoftwarearchitectureofMMI.Takingatypicalapplication,phonebookasanexample,makestherequirementanalysisandpracticalplandesignfirstly.Thengoesdeepintothedetailedrealizationoffunctionandinterface,andfulfillsthecommunicationbetweenrelatedapplications.Inthelaterperiod,accordingtotestcase,finishestheBlack-boxTestinganddebugging.Finally,passesallthetestingofsoftwareandhardware,whichverifiesthevalidityandfeasibilityoftheearlydesign,finishedproductshavebeenpouredintomarket.Keyword:HandsetMan-Machine-Interface(MMI)MTKBlack-boxTesting 目录第一章绪论11.1手机发展现状11.1.1移动通信的发展11.1.2手机软件开发平台11.1.3手机软件分类21.2课题的现实意义21.3论文的工作和结构3第二章手机系统结构52.1手机硬件结构52.2手机软件结构62.2.1移动通信协议体系结构62.2.2软件设备驱动[16]82.2.3手机操作系统92.2.4人机交互接口MMI112.3手机嵌入式系统112.3.1多任务处理机制112.3.2基于优先数的任务调度122.3.3任务间的通信122.3.4任务间的同步132.4小结13第三章MMI的研究与分析153.1MTK平台总体设计153.1.1适配层KAL153.1.2适配层L4[22]163.1.3task间的通信机制[23]173.2MMI层软件结构[24]183.2.1MMI接口介绍193.2.2MMI与L4之间的通信193.3Framework层[25]223.3.1事件处理器223.3.2历史管理243.3.3OSL层243.3.4NVRAM253.3.5文件系统26 3.4UI层273.5Application层273.6小结29第四章通讯录应用的设计与实现314.1初步设计与分析314.1.1系统需求分析314.1.2模块设计思路334.2初始化详细流程设计364.3界面显示的设计与实现404.3.1一、二级菜单设计404.3.2编辑框的设计414.3.3弹出窗口的设计424.3.4窗口绘制与History管理设计444.4核心功能的设计与实现464.4.1显示电话号码列表464.4.2添加新条目484.4.3删除已有条目494.4.4姓名查找514.4.5复制或转存524.4.6相关设置功能524.5应用间的交互534.6高级功能快速查找544.7小结55第五章手机应用层的软件测试575.1手机应用层软件测试方法[35]575.2MTK平台软件仿真工具[36]595.3通讯录应用的测试用例625.3.1基本功能测试635.3.2批量测试645.3.3失败测试655.3.4集成测试675.4通讯录应用的测试结果67第六章总结与展望71致谢73参考文献75 第一章绪论3第一章绪论1.1手机发展现状1.1.1移动通信的发展从1876年贝尔发明电话以来,经历了长达一个多世纪的发展,电话通讯服务已走进了千家万户,成为国家经济建设、社会生活和人们交流信息所不可缺少的重要工具。在最近二十年中,通讯技术和业务发生了巨大变化,通信的地点也由固定方式转向移动方式。随着现代生活节奏越来越快,移动通讯发展迅猛,其通讯工具手机的更新换代和市场争夺战也愈演愈烈。国外手机生产企业认为质量和信誉是品牌的保证。同时,他们针对手机这种特殊商品的特点,即科技产品和时尚产品二位一体,致力于研究创新,从外型、功能、质量等方面不断改善力求做到尽善尽美。手机不再只是用来通话的,它已经成为一个集照相机、游戏机、音乐播放器、电影院……等强大功能为一身的电子消费品。例如,诺基亚的主要目标消费群是中高收入的白领阶层,摩托罗拉则是以追求潮流与时尚的年轻族为目标。同时,他们很重视促销、售后服务等一系列提高品牌价值和产品附加值的营销环节。国内在营销机理及营销管理的研究上,无论从框架体系,还是方法手段乃至观念都难于超越国外模式,基本上处于追赶型研究状态,但我国与国外研究的差距显然在以递增的速度缩小。目前,我国手机市场有30多个品牌,生产厂商40多家。整个手机市场保持着“寡头”格局,诺基亚、摩托罗拉、三星、索爱、飞利浦、NEC等著名外资品牌市场份额在四分之三。其余被以联想、波导、夏新、TCL为龙头的国产手机瓜分,他们在国家政策的扶持下,守护着国产品牌的尊严。我国部分的手机生产商已基本掌握了协议栈软件、应用软件的开发,以及整机电路、模具、造型的自主设计、大生产技术与产业化,个别企业还掌握了基带、射频等核心芯片设计、物理层软件开发技术,并拥有整机设计能力,我国手机及多媒体信息终端产品的研发技术水平得到显著提高。手机所需的大部分元器件都可以在国内生产,移动通信产业链已基本形成[1]。1.1.2手机软件开发平台手机开发分为硬件、软件开发。硬件就是指外观设备、芯片等,而 第一章绪论3软件分为底层软件、应用软件。其中芯片设计是相对技术含量高的环节,其市场长期为国外厂商所垄断。国内厂商在04-05年间起步发展,新进厂商采用降低芯片成本、芯片附赠软件平台的模式,逐渐占据国内手机市场。手机芯片包含基带处理器、射频芯片、应用处理器等,可为音频、视频等多媒体配备相应自己的芯片[2]。国外厂商有Ti、FreeScale、ARM、Intel、ADI、高通等,国内厂商有MTK、展讯、大唐移动、凯明、鼎新等。据iSuppli公司数据显示,2006年MTK基带市场份额为44%。国内手机采用MTK芯片的品牌有:联想、天阔、普天、三新、三盟、宇宙、南方高科、诺科、康佳、科健、采星、迷你、波导、CECT、TCL、奥克斯、东信、长虹、托普、吉事达等。MTK是联发科技股份有限公司的英文简称,它作为全球IC设计领导厂商,专注于无线通讯及数位媒体等技术领域。公司提供的晶片整合系统解决方案,包含无线通讯等在市场上居领导地位。在MTK的手机解决方案中,将手机芯片和手机软件平台预先整合到一起。这种方案可以使终端厂商节约成本,加速产品上市周期。MTK公司的产品因为集成较多的多媒体功能和较低的价格在大陆手机公司和手机设计公司得到广泛的应用。MTK的Turn-key方案(将芯片与手机开发所需的软件平台乃至第三方软件捆绑销售)的巨大成功则证明了在这一领域平台技术不再是TI、英飞凌这些巨头的专属。这一策略使得MTK在手机市场取得了骄人的业绩[3]。但是并不是所有的国产手机都简单的运用MTK最被人称颂的totalsolution,而是“取其精华”,利用自己对市场的理解生产出具有自身特色的MTK手机。例如成功坐上了国产手机的第一把交椅的天语手机。1.1.3手机软件分类按照软件安装的方式来分类,可以将手机软件分为前装软件和后装软件。前装软件是指在手机用户购买手机的时候,已经预先安装在系统内的软件。如通讯录、短信息等是设计厂商捆绑在操作系统的前装软件;后装软件是指在用户购买手机之后,通过下载或者与电脑连接等方式获取并安装的软件。按照应用类型分类,可以分为基本功能类(如通讯录、短消息)、信息资讯类(如腾讯QQ),工具类(如地图),娱乐类(如影院),游戏类等。1.2课题的现实意义本课题来源于本人在实习公司参与的手机研发项目A302,以其中的通讯录模块为例,详细阐述了GSM网络中MTK平台应用层软件的设计与实现。本项目的客户要求是希望从界面外观、功能操作等各方面,在MTK平台上达到与某款手机高仿的效果。因此本课题的实践背景是基于MTK的totalsolution 第一章绪论3方案,按照用户需求并结合手机应用软件开发平台中的应用层概念,在应用层基础版本上进行基本功能类、前装软件的MMI二次开发。移动终端的应用层软件需要嵌入式实时操作系统的支持,基于一定的嵌入式操作系统提供操作系统抽象层,便于上层应用软件的开发和移植。应用层软件即人机交互接口(MMI)所反映出来的界面,其操作之简易性对于移动终端产品的优劣也具有举足轻重的作用。它是相对独立于通信设备标准的,有利于二次开发和项目移植,对于嵌入式移动终端应用软件的研究具有长远的现实意义。另外,从市场效益的角度来说,不仅给公司带来了可观的经济价值,同时又为消费者购买移动终端产品提供了一个更有竞争力的选择。1.3论文的工作和结构在研发手机项目中,对通讯录模块研究与开发的工作经历了四个主要阶段:第一阶段:学习阶段。在原有移动通信的理论基础上,进一步对移动通信系统进行深入学习,阅读大量数字移动通信系统的书籍,着重于对移动终端所涉及到的理论进行有针对性的学习,为后续的工作奠定了良好的专业理论基础。同时,为了更好的进行软件设计,阅读了MTK平台软件设计的相关文章和文档,并参阅软件工程的书籍,学习必要的软件设计知识。对整个手机系统软件的架构进行把握。第二阶段:设计阶段。在了解了移动通信终端协议体系和整个手机架构的前提下,对通讯录模块进行了总体设计。第三阶段:应用阶段。理论结合实践在手机软件平台上设计实现了通讯录模块的基本操作(如电话条目存储、删除、复制等)、来电免打扰、快速拨号等全部功能和界面。第四阶段:测试阶段。通过严格测试,并在程序结构上进行优化。根据实习期间所完成工作,将论文结构安排如下:第一章绪论本章通过对比国内外手机发展先介绍了移动通讯的发展情况,然后分析了手机市场最大竞争力——软件开发平台,由此简单介绍了项目应用平台MTK。最后阐明了本课题的实践背景、现实意义和论文各章节安排。第二章手机系统结构本章分析了手机平台的硬、软件结构。在软件结构中重点介绍了移动通信体系结构,用举例对比的形式介绍了几种常见的手机操作系统。最后着重阐述了手机嵌入式实时操作系统中的核心概念。第三章MMI的研究与分析 第一章绪论3本章首先分析了MTK平台的总体结构。由于项目针对的是MMI层软件开发,开始重点分析MMI的软件结构。其中主要介绍了MMITask运行机制、重要接口,以及MMI的各个模块。第四章通讯录应用的设计与实现本章以通讯录模块为例,详细阐述了如何对该模块进行需求分析和设计,并在MMI层实现了通讯录各功能及相应界面。第五章手机应用层的软件测试本章首先列举了手机应用层软件测试方法,然后介绍了一个重要的调试工具——MTK平台提供的软件仿真工具MoDIS。通过编写的通讯录应用的黑盒测试用例完成测试,最终给出测试结果。第六章总结与展望本章总结课题结果、不足之处以及展望。 13第二章手机系统结构第二章手机系统结构2.1手机硬件结构手机电路由无线收发信机、基带信号处理电路、基带控制电路、存储电路、键盘、显示器、外部接口等部分组成[4]其硬件结构,如图2.1所示。MT6205GSMBasebandMT6119RFTransceiverMBuzzerBatteryFET+0.2ΩDCinT/RSwitchPATXVCOVCOPLL26MHzVCTCXOI/QControlDSP52MHzDSPCoprocessorsMCU/DSPInterfaceRAMROMJTAGDebug256KbRAMARM7TDMI26MHzROMTDMATimerPLLRTCPWMLCDGPTSIMEMIWTDInterruptsDMAsSystemBusGPIOFlashUARTKPSubLCDSRAMMainLCDADCDACADCDACPowerSuppliesSIMCard123456789*0#MT6305PMIC图2.1手机硬件结构1.射频单元射频单元的发信通路将基带单元产生的270.833Kbit/s的TDMA帧数据流信号按GMSK调制方法形成I、Q信号,再调制到900MHz或1800MHz射频信号,经射频开关由天线发射出去,收信通路将天线接收的信号经低噪声放大、解调产生基带I、Q信号,通过解调和均衡将模拟的I、Q信号进行数字化,恢复出数字基带信号,送基带电路处理。射频单元的本振信号通常从时基电路获得基准频率,然后采用锁相环技术实现频率合成。 13第二章手机系统结构2.基带芯片与基带信号处理电路基带芯片是通信终端产品的关键部件,现在流行的一般有单IC和双IC封装两种形式。多家公司可以大量供应成套的芯片组。基带信号处理电路包括信道编/译码、加密解密、TDMA帧形成/信道分离及基准时钟电路、话音编/译码、码速适配器等。送话器的话音信号经过8kHz抽样及A/D变换,成为均匀量化的数据流,经话音编码、信道编码、交织、加密等处理,形成270.833Kbit/s的TDMA帧数据流,送调制器发送。在接收通道执行与发信通道相反的过程。帧及信令控制以时钟基准部分提供统一帧号、时隙号、1/8bits时钟等基础,实现同步。3.控制器控制器实现对手机系统的控制,包括协议处理、射频电路控制、基带电路控制、键盘输入、显示器输出、SIM卡接口及数据接口等功能。2.2手机软件结构手机系统软件主要由:移动通信协议栈、设备驱动、操作系统、MMI和WAP组成。2.2.1移动通信协议体系结构GSM协议的分层原理来自于开放式系统互连(OSI)参考模型[5-7]。根据协议分层的概念,通信处理过程可以看作由最低层到最高层的若干有序的逻辑层次构成,每层都存在实体单元。最低层是信息在两个远距离实体之间的物理传输,要依赖物理介质,而最高层代表外部用户的观点。每一层向它的上层提供服务,这些服务是对下一层提供服务的扩充。GSM协议栈分为三层:物理层、链路层、网络层,如图2.2中的L1、L2、L3。第三层L3第二层L2第一层L1第三层L3第二层L2第一层L1中间层数据链路层物理连接MS侧网络侧SMSCCSSMMRMLAPDm物理层模块管理子层第三层第二层物理层MS的Um接口信令软件总体框图图2.2GSM协议结构分层模型 13第二章手机系统结构第一层:物理层。物理层是协议体系中的最低层,它包括各类信道,为高层信息的传输提供基本的逻辑信道;每个逻辑信道都有自己的服务接入点(SAP),移动台的接入方式采用多址接入方式,可以在空闲时间检测周围的无线电环境,把检测结果定时的传给基站,确定是否进行小区切换。第二层:链路层。链路层属于中间层[8-10](LAPDm:LinkAccessProtocolforDmChannelDm信道链路连接协议)。它包括各种数据传输结构,对数据传输进行控制。LAPDm的基本功能是把单个的bit构成一个集合,以便在移动台和基站之间提供可靠的无线数据链路,所有的链路功能都是建立在这个基本结构单元上,这个单元称为帧,帧的结构采用HDLC(高层数据链路控制)的定义方式。链路层协议主要由GSM04.05、04.06系列标准来描述[11]。第三层:网络层。第三层实体提供在一个蜂窝移动网和其相连接的其他公众移动网中建立、维护和终止电路交换连接的功能。还要提供必要的补充业务和短消息业务的控制功能。按照第三层实体所要完成的功能可以分成无线资源管理(RR)、移动管理(MM)和连接管理(CM)三个子层(CC、SMS、SS)。无线资源管理子层(RR):提供的功能是完成与物理传输资源有关的管理。提供的服务包括:专用物理信道的建立与维持、应网络请求而进行的越区切换、信道传输模式的改变和质量测量等。移动管理子层(MM):具有支持移动用户的移动特性所必须的功能。提供的服务包括:当移动台激活与去激活时,或者用户所处定位区改变时,MM实体负责通知网络;MM实体不需要完成用户身份鉴别和注册的工作。连接管理子层(CM):包括呼叫控制(CC)、短消息业务(SMS)和附加业务(SS)实体。呼叫控制具有为建立与拆除MS端主叫和被叫时的电路交换连接所必须的功能,提供的服务包括:发起呼叫、连接呼叫和释放呼叫等[12];短消息业务支持完成各种补充业务,如:呼叫转移、来电号码显示等;附加业务实体则支持完成点到点或广播短消息内容的接收与发送。我们现将协议体系进行必要的转化,提出协议栈的概念,并按协议规范对协议栈的功能确定如下。所提到的协议栈是对应与GSM标准[13-15]的L2和L3层,同时此协议栈还实现L3层之上的短消息的第四层和第五层结构,分别为中继层(SM-RL)和传输层(SM-TL)。此外,此协议栈还需要支持SIM卡单元和小区广播的功能模块。由协议栈总体结构的描述可知,L3层是整个协议栈的核心,它包括了大部分的手机功能实现。它提供一个蜂窝移动网和与其相连接的其它公共移动网之间的建立、维护和释放电路交换的功能;提供必要的支持补充业务、短消息业务和呼叫控制的功能;L3还包括移动管理和无线资源管理的功能。此外,最新开发的L3 13第二章手机系统结构层应当能支持GPRS业务,并提供相应复杂的控制功能。在软件设计过程中,L3层主要由大量的程序模块构成,这些程序块在第三层各主体之间、第三层与相邻层以及相关层之间传递携带各种信息的消息单元。因此可以说,解决了L3层协议的设计也就基本上解决了整个协议栈软件的设计工作。2.2.2软件设备驱动[16]设备驱动主要用来解释来自MCU的命令,实现对外设的控制。这个模块处理许多用户可见的手机行为,例如键盘处理、LCD显示。该模块通过函数调用或与L4实体进行消息交互的方式被引用,通过访问设备寄存器来提供必要的控制功能。手机系统中的软件设备驱动如图2.3所示:UARTSPIAUXtaskBMTPMICCameraUSBtaskMSDCGPT,RTC,WDTPWM,AlerterJPEGDecoderADCSchedGPIOKeyPadLCDIrDAtaskSIM图2.3软件设备驱动外设的功能解释如下:SIM:用户识别模块,写入用户信息UART:通用异步收发设备SPI:串口界面LCD:液晶显示器GPIO:通用输入输出RTC:实时时钟。当要求在某个时间闹铃,或者在某个时间段给MMI发送消息提示(以1秒为基准),这就由软件clock模块读写RTC。WDT:看门狗计时器GPT:一般设定的时钟PWM:脉冲宽度调制Alerter:报警设备KeyPad:键盘,该模块处理所有从键盘发送来的信息,处理后并把按键信息发给上层。 13第二章手机系统结构PMIC:电源管理芯片BMT:电池充/放电管理AUXtask:耳机taskUSBtask:USBI.1协议和驱动IrDAtask:IrDA和驱动MSDC:内存卡驱动,支持SD、MMC卡和内存片Camera:照相机JPEGDecoder:控制硬件JPEG解码器的软件2.2.3手机操作系统现在市场上流行三类手机嵌入式操作系统[17]:第一类是“实时操作系统(RTOS)”。其目的主要是驱动硬件,任务调度。这类操作系统一般是封闭系统,也就是一旦手机出厂,这类手机不能直接动态加载新的软件应用。RTOS手机使用相对简单,经济实惠。对多数只把手机当做通讯工具的人来说,事先预装浏览器、彩信、三到五款游戏也就足够了。这类手机操作系统的主要代表为Nucleus、ThreadX、uC/OS、RT-Linux等。对于智能手机来说,RTOS需要借助JAVA中间件等来扩展业务,运行效率问题比较突出。第二类是“智能手机操作系统”。在完成第一类手机操作系统任务的基础上,这类系统进一步加强人机交互的一致性体验,强调多任务之间的协同操作,规范程序间通讯和编程模型。这类系统也被称为开放式操作系统,即手机出厂后,消费者可以借助于个人计算机,手工从因特网上下载新软件、游戏等。智能手机操作系统的主要代表为Symbian、WinCE、PalmOS、Linux等。它们的软件体系架构沿用PC模式,即软件要事先安装到本地永久存储器之后才能使用。第三类是“网络软件运行平台”。其目的是在第二类手机操作系统之上,构建一个所谓“中间件”平台。消费者可以很容易地、动态地、透明地下载移动电讯网上的一些新兴增值业务、游戏等,无需个人计算机作为扩展手机业务的中介。这类手机操作系统有JAVA、BREW、WIPI(韩国标准)等。由于GPRS带宽和流量费的限制,这类手机操作系统现在还不是主流。在网络软件运行平台上,消费者无需事先安装软件,软件可以直接下载到内存里运行。这类软件的使用和维护也比PC模式简单很多。下面介绍市场上主流的手机操作系统[18]:1.Symbian系统Symbian是一个实时性、多任务的纯32位操作系统,具有功耗低、内存占用少等特点,非常适合手机等移动设备使用,经过不断完善,可以支持GPRS、蓝牙、 13第二章手机系统结构SyncML,以及3G技术。最重要的是它是一个标准化的开放式平台,任何人都可以为支持Symbian的设备开发软件。与微软产品不同的是,Symbian将移动设备的通用技术,也就是操作系统的内核,与图形用户界面技术分开,能很好的适应不同方式输入的平台,也可以使厂商可以为自己的产品制作更加友好的操作界面,符合个性化的潮流,这也是用户能见到不同样子的Symbian系统的主要原因。现在为这个平台开发的java程序已经开始在互联网上盛行。用户可以通过安装这些软件,扩展手机功能。2.WindowsCE系统WindowsCE系统包括PocketPC和Smartphone,前者针对无线PDA,后者专为手机,已有多个来自IT业的新手机厂商使用,增长率较快。PocketPC2002推出了应用在手机上的PhoneEdition(电话版本),国内贴牌机多普达686就使用了这个系统。不过它在移动通讯方面的功能并不是很全面。针对这种情况,微软于2002年底发布了专门为手机开发的操作系统SmartPhone2002,像SymbianPearl一样,是专为移动通讯设备开发的系统。虽然从众多手机厂商的反应来看,全球手机五大厂商中只有三星购买了微软的软件许可,故其在手机市场上占有率不高。3.Linux系统Linux系统件是一个源代码开放的操作系统,目前已经有很多版本流行。但尚未得到较广泛的支持,其发展的最大阻力在于它对硬件要求比较高,而且没有一个强有力的推广方。这样就导致Linux手机的成本比较高,而且版本混乱。但Linux的优势也相当明显,首先它是免费的,其次它是开源的,每一家愿意的厂商都能够加入到Linux操作系统的底层开发中。4.Palm系统PalmOS是Palm公司的是一种32位的嵌入式操作系统,它的操作界面采用触控式,差不多所有的控制选项都排列在屏幕上,使用触控笔便可进行所有操作。作为一套极具开放性的系统,开发商向用户免费提供Palm操作系统的开发工具,允许用户利用该工具在Palm操作系统的基础上编写、修改相关软件,使支持Palm的应用程序丰富多彩、应有尽有。5.非智能手机操作系统低端手机也有操作系统,但功能非常简单,主要支持通讯录调用等。对于非智能手机设计生产商来说,不追求系统的强扩展性和第三方软件的添加,一般手机操作系统只需提供核心功能,如多任务调度、中断、通信机制等,便于上层应用软件的开发和移植即可。例如:MTK平台使用NucleusPlus操作系统,Brew平台使用的是rex(Real-timeExecutivesystem)操作系统,展讯平台操作系统抽象层支持的是Threadx操作系统。Nucleus 13第二章手机系统结构Plus是美国源代码操作系统商ATI公司推出的新一代嵌入式操作系统,属于抢先式实时多任务操作系统内核,95%的代码使用ANSIC编写,非常便于移植于各种处理器家族。从实现的角度讲,不同于传统嵌入式开发,NucleusPlus是以函数库的形式链接到目标应用程序中,形成可执行目标代码,下载到目标板上或烧到ROM/FLASHROM中去执行。NucleusPlus内核在典型的CISC体系结构上占据大约20k空间,而在典型的RISC体系结构上占据空间为40k左右,其内核数据结构占据1.5k字节的空间。2.2.4人机交互接口MMI随着社会的发展,人们对手机的要求越来越高,良好的通话质量,美观的外形,友好的人机界面,已成为人们追求的目标。因此,手机人机界面的设计和开发无论对用户还是对公司,都日益重要。其主要提供移动台(手机)的全面控制和手机与用户之间的接口,功能包括:用户键盘输入、手机状态和呼叫处理过程显示、SIM卡和通讯录的管理、PIN码的控制、缩位拨号等。2.3手机嵌入式系统实时操作系统(RealTimeOperatingSystem)是根据操作系统的工作特性而言的。实时是指物理进程的真实时间。实时操作系统是指具有实时性,能支持实时控制系统工作的操作系统。首要任务是调度一切可利用的资源完成实时控制任务,其次才着眼于提高系统的使用效率,重要特点是要满足对时间的限制和要求。2.3.1多任务处理机制在嵌入式实时系统中,进程(或任务)是操作系统的核心,操作系统的存在归根结底就是为了提供一个运行程序的空间。多任务系统的执行过程实际上就是一系列任务在三种状态中循环流动、轮流被内核调度的过程。每个任务都是一个无限的循环,而且在同一时刻可运行的任务只能处于运行态、就绪态或阻塞态三种基本状态之一[19]。如图2.4所示:运行就绪阻塞被调度时间片用完资源释放或事件完成等待资源或事件图2.4任务状态及转化 13第二章手机系统结构在市场推动下,手机功能在不断发展。摄像头、MP3、蓝牙这些功能可以依靠硬件,对CPU的压力还不是很大。但java虚拟机、嵌入式浏览器等应用软件就会对CPU资源有较高的要求。不管是单CPU还是双CPU,多任务机制在手机中就显得非常重要。在同一时间我们会有许多的事情要去做,比如进行电源管理,协处理器管理,文件系统管理,串口管理,显示管理,SIM卡管理,LCD显示管理,用户输入管理等等。如果是单任务串行机制,那么操作系统的实时性就无法保证了。2.3.2基于优先数的任务调度每个进程都有一个优先数,数值大的表示优先级高,系统在调度时总选择优先数大的占用CPU。优先数的确定有两种:静态优先数法:进程创建时就规定好它的优先数,这个数值在进程运行时不变。确定数值时可以考虑采让外设进程或终端用户进程优先。动态优先数法:进程的优先数在执行过程中可以根据情况而改变。大多数的嵌入式实时操作系统使用的是基于优先级的可抢占式调度策略,应当采用优先级继承和优先级天花板策略来解决和避免优先级反转问题。手机嵌入式系统中,任务优先级的概念体现在窗口管理机制上。设置窗口优先级的目的是为了保护那些重要的窗口不被打断。例如,当手机在呼叫状态时是处于Call窗口的,在Call的过程中不能够出现被SMS或者Alarm窗口打断的情况,否则会影响正常的Call过程。2.3.3任务间的通信在一个实时系统中,可能有许多任务作为一个应用的一部分执行。系统必须提供这些任务间的快速且功能强大的通信机制。两个并行进程可以通过互相发送消息进行合作,消息是通过消息缓冲而在进程之间相互传递的。任务之间的通信有三种方式:信箱、队列FIFO和管道PIPE。1.信箱信箱是任务间发送消息的接口,也是OS提供的一种机制。每个任务可以定义一个信箱,其他任务可以给它发送消息。每个消息的结构中有个是信号量,它与某一事件联系,而此事件是由于信箱中来了消息激发的。然而如果一个任务需要从多个信箱中得到消息,它必须能够知道事件的标识和事件已经发生。信箱可以看成是长度为1的队列,它消耗的资源少于队列,运行速度快于队列。2.队列FIFO 13第二章手机系统结构FIFO是一种先进先出的队列。它类似于一个管道,只允许数据的单向流动。每个FIFO都有一个名字,允许不相关的进程访问同一个FIFO。因此也成为命名管。3.管道PIPE管道一般用于两个不同进程之间的通信。当一个进程创建一个管道,并调用fork创建自己的一个子进程后,父进程关闭读管道端,子进程关闭写管道端,这样提供了两个进程之间数据流动的一种方式。2.3.4任务间的同步内核也要提供为了有效地共享不可抢占的资源或临界区所需的同步机制。任务之间的同步有三种方式:信号量、事件组和信号。1.信号量(semaphore)信号量提供了对临界资源的控制机制。所谓的临界资源指的是在同一时刻只能为一个用户所使用的资源。对信号量的基本操作是得到(obtain)和释放(release)信号量。得到信号量是信号量的值减少;释放信号量使信号量的值增加。2.事件组(eventgroup)事件组提供一种机制,指明了某种系统事件的发生。一个事件由在事件组变量中的某一位(bit)来代表,该位被称为一个事件标志。事件标志的使用是同步的,任务并不知道事件标志的出现直到出现特定的服务请求。通常每个事件组中有32个事件标志。3.信号(signal)信号以异步方式操作,当信号出现时任务被中断,一个先前被任务定义的特定的信号处理程序被执行。每一个任务具有处理32个信号的能力。每一个信号由变量的一位(bit)代表。2.4小结在本章中首先介绍了手机的硬件结构和软件结构,其中详细研究了移动通信协议体系结构,并用对比的方式介绍了流行的嵌入式实时操作系统,最后重点对嵌入式实时系统的特点做了详细的分析。本项目是基于GSM网络,从界面、功能、外观等各角度在MTK平台上达到高仿某款手机的效果。而该款手机采用的Symbian操作系统在智能移动终端上拥有强大的应用程序以及通信能力,它的特征包括文件系统、图形用户界面框架、多媒体支持、TCP/IP栈和库,提供的软件开发包可以供第三方应用程序开发使用。 13第二章手机系统结构Symbian体系中有多个可选择的UI平台以适应不同的用户需求。这些优点是普通手机平台难以实现的,当然这也是本项目的难点所在。因此,项目的首要任务是先对原始需求进行充分评估和合理设计。 29第三章MMI的研究与实现第三章MMI的研究与分析3.1MTK平台总体设计手机软件主要包括运行软件和调试软件两大部分。本项目中运行软件主要由:GSM协议栈、Nucleus操作系统、设备驱动、MMI和WAP模块组成。MTK提供的调试软件有:Catcher、META[20]。它们的作用在于监视软件的实时运行,加速手机运行软件的开发。整个软件的结构如图3.1所示:CatcherMETAJAVAMMIWAPL2/L3ProtocolStackDriversL1ProtocolStackL4CckNucleusOS图3.1MTK软件结构其中,Drivers是整个系统外围设备的驱动程序,WAP是无线应用协议,JAVA是J2ME软件。3.1.1适配层KALMTK平台使用了NucleusPlus实时操作系统。本系统设计了一个操作系统适配层(KAL)在其上做了个内核抽象层的封装,使得手机软件独立于Nucleus操作系统。为了确保MMItask上所有程序能在PC机上正常的运行,这层是必须的。它封装了一些API,它们为其他软件提供了很多系统服务函数,例如时钟管理、任务管理(同步和通信)、资源管理,内存管理等[21]。如图3.2所示: 29第三章MMI的研究与实现OSLKALNucleusorotherRTOS图3.2适配层KAL3.1.2适配层L4[22]MTK平台中,L4层是MMI与AT和协议栈之间的一个适配层。也就是说,二者通过L4层完成通信过程。一般地,我们将L4以下的部分称为下层,上面的称为上层或应用层。详细结构如图3.3所示:KALOSadaptationNucleusOSDriverPS/L1RMI(AT)FMIATCIL4AL4CUEMSMUSMSALCSMTCMENGPHBRACL4图3.3适配层L4MMI:包括RMI和FMI两个部分。前者即远程MMI(例如,PC端),通过UART口利用AT命令与协议栈通信;后者包括了MMI的所有特性。L4A:FMI对应的L4适配层,FMI和L4A之间的服务节点是原始节点。 29第三章MMI的研究与实现L4C:L4的控制实体,处理所有应用的请求和响应。ATCI:AT命令解释器,解释来自PC端的AT命令,同时命令L4C执行相应的动作。UEM:用户设备适配。驱动的适配,如KEYPAD、LED、GPIO等。PHB:电话本管理。处理电话本的相关操作,如存储等。SMU:安全管理单元。安全性管理以及STK。CSM:电路交换协议栈管理。RAC:注册接入控制。包括GSM/GPRS的注册管理等。SMSAL:短消息服务应用层。处理短信存储、收发短信、小区广播等。TCM:终端文本管理。3.1.3task间的通信机制[23]在MTK平台中,系统被划分为若干个独立的task,它们由操作系统来统一管理调度。一个事件的处理往往是多个task交互完成的,这就需要每个task之间都可以进行通信,它们都是通过消息队列来接受或发送消息的。如图3.4所示:CCTaskSIMTaskL4TaskMMITaskmoreTask…MODL4CMODTCMMODSMSALMODCSMMODUEMMODRACMODSMUMODPHBSystem图3.4task结构消息队列可以分为三种:内部队列Internalqueue、外部队列Externalqueue和循环队列Circularqueue。其中,内部队列是在同一个task的模块之间进行消息交互的队列,外部队列是在不同的task的模块之间进行消息交互的队列,循环队列是专门用于MMI模块读取消息的队列,默认的大小是30。消息message的数据结构定义如下:typedefstructilm_struct{oslModuleTypeoslSrcId;//源模块IDoslModuleTypeoslDestId;//目的模块IDoslMsgTypeoslSapId;//服务接入点oslMsgTypeoslMsgId;//信息名IDoslParaType*oslDataPtr;//本地参数缓冲器 29第三章MMI的研究与实现oslPeerParaPtr*oslPeerBuffPtr;//peer缓冲器指针}ilm_struct;进行task之间的通信之前,先创建task。建立task入口函数,进入消息的循环,从而在外部队列中监听消息message,完成此步骤的函数是:OslReceiveMsgExtQ(mmi_qid,&mmi_message);下面以MMItask向L4task发送消息来说明task间的通信过程:1.建立一个本地参数的缓冲器2.分配需要的值到本地参数缓冲器3.在结构体ilm_struct中填写相应信息4.发消息给L4CMMI从L4C中接收到消息后,MMI会根据消息ID注册一个消息响应的处理函数,完成此步骤的函数是SetProtocolEventHandler(FuncCB,msg_id)。以MMI向L4C发送调节音量请求为例:voidSetVolumeLevelReq(volume_type_enumvolume_type,U8volume_level){MYQUEUEMessage;mmi_eq_set_volume_req_struct*setVolumeLevelReq;Message.oslMsgId=MSG_ID_MMI_EQ_SET_VOLUME_REQ;//消息ID//建立本地参数缓冲器setVolumeLevelReq=OslConstructDataPtr(sizeof(mmi_eq_set_volume_req_struct));setVolumeLevelReq->volume_type=volume_type;setVolumeLevelReq->volume_level=volume_level;Message.oslDataPtr=(oslParaType*)setVolumeLevelReq;//本地参数缓冲器Message.oslPeerBuffPtr=NULL;//Peer参数缓冲器Message.oslSrcId=MOD_MMI;//源模块IDMessage.oslDestId=MOD_L4C;//目的模块IDOslMsgSendExtQueue(&Message);//发送给L4task}3.2MMI层软件结构[24]MMI模块主要由三部分组成:ApplicationLayer(应用层软件)、Framework(框架)和UILayer(图像用户接口)。它们之间的关系如图3.5所示: 29第三章MMI的研究与实现ApplicationLayerUILayerFrameworkOperatingSystem&ProtocolStackLayer&Driver图3.5MMI软件结构ApplicationLayer即手机应用,就是手机提供的各功能。具体包括通讯录、消息(短消息、增强型短消息、小区广播)、历史记录、设置(电话设置、网络设置、安全设置)、情景模式、娱乐游戏、WAP、快捷方式等。Framework是MMI模块的核心,主要用于分发和解释消息并控制向用户提供友好界面的信息,接收到的消息按其属性逐层解析处理。包括OS适配层、与L4task通信的Task和与存储设备通信的文件系统。UILayer主要负责人机界面元素,实现菜单的组织和屏幕的显示。例如:主题风格、标题、按钮、图片等的组织和调用LCD驱动显示人机界面。由此可以说Framework主要实现了调度功能;ApplicationLayer实现各个服务功能,每个功能又自己组成一个模块,设计时可根据具体需求增减模块;UILayer负责显示用户友好界面。为了增强软件的可扩展性和灵活性,特意将Framework和ApplicationLayer分开,利于模块的封装和程序的二次开发。3.2.1MMI接口介绍MMI中主要接口包括:Framework与协议栈L4层的接口,也是MMI层与应用提供者的接口。它们之间时通过消息进行通信的,是由Task机制来完成的。UILayer与LCD的接口,也是MMI与硬件的接口。UILayer先与LCD驱动通信,然后通过驱动与硬件设备连接。它们是通过接口和消息进行通信的。3.2.2MMI与L4之间的通信MMITask与L4Task的通信过程如图3.6所示: 29第三章MMI的研究与实现网络模拟器/L4MMI队列网络模拟器/L4队列MMITASK操作系统层图3.6MMITask与L4Task的通信过程MMI队列:协议栈或者L4将事件写到该队列中,然后MMITask从这个队列中读取事件。网络模拟器/L4队列:MMITask将MMI事件写入该队列中,然后L4task或者网络模拟器从这个队列中读取事件。MMITask的运行过程如图3.7所示:FrameworkEventHandlerHistoryOSLNVRAMFileSystemEventsFrom/ToL4CATEGORYSCREENSAPPLICATION层UI层UIELEMENTSIMAGESFONTSTHEMESGRAPHICS库WRAPPERSGRAPHICS库IMPLEMENTATION图3.7MMITask运行过程此图中我们可以看到该过程如下:1.等待发送给MMI队列的messages2.协议栈把messages写入到MMI队列中3.Framework层处理事件4.Framework层调用ApplicationLayer中注册过的回调函数5.ApplicationLayer调用UI层的类屏幕函数来组织UI元素,使之呈现在界面上下面举例来说明MMITask中的事件流: 29第三章MMI的研究与实现1.按键事件(向ApplicationLayer发送)协议栈/L4MMI队列APPLICATIONFRAMEWORK按键事件图3.8按键事件一旦有键按下,MMI运行机制如下步骤工作:l协议栈将此事件写入MMI队列中;lMMITask从MMI队列中读该事件;lFramework调用回调函数,在ApplicationLayer注册事件;lApplicationLayer接收到按键事件给出响应。2.播放声音请求(ApplicationLayer向底层发送)协议栈/L4L4队列APPLICATIONFRAMEWORK图3.9播放声音请求应用层发送播放声音请求时,MMI运行机制如下步骤工作:lApplicationLayer给Framework层发送呼叫请求,要将信息传送给L4队列中;lFramework层将信息写入L4队列;lL4task从L4队列中读出事件,播放先前请求的声音。 29第三章MMI的研究与实现3.3Framework层[25]Framework作为MMI的核心,它的作用体现在如下三个方面:第一,用于接收来自所有Task的事件。第二,帮助ApplicationLayer控制屏幕流。第三,且为系统提供调用应用时所需的数据包,例如消息分发时写入到队列中的数据包。从图3.7可以看出Framework结构上分成五个部分:1.事件处理器(EventHandlers)功能:为各种事件注册和执行Applications中对应的回调函数。事件分类:A.协议栈事件(protocolevents):用于底层和MMITask通信。它是最基本的事件,每一个协议栈事件都有唯一ID标识。例如来电情况中,L4层产生INCOMING_CALL_EVENT,同意接听后,MMI将产生CALL_ACCEPT_EVENT。B.高亮事件(highlightevents):基于按键事件的一种人为事件。有时伴有hintinfo(提示信息)。当前按键指示在某一菜单项时,Framework产生一个highlight事件,Applications利用事件执行,菜单项被高亮、键盘匹配、左右软键改变。SetHiliteHandler函数中也有两个参数,一个是某个菜单项ID,一个是该菜单项对应的入口函数。C.按键事件(keyevents):用户键盘操作时产生的事件。本质上也是一种协议栈事件,由L4task传给MMItask。2.历史管理(History)功能:帮助应用层保留屏幕流和存储中间数据。3.OSL功能:根据应用的命令向所有的操作系统提供数据包。4.NVRAM功能:为数据存储提供数据包,从NVRAM中重新获得数据。5.文件系统(FileSystem)功能:为数据存储提供数据包,从FileSystem中重新获得数据。3.3.1事件处理器前面已经对事件进行了分类,现在通过协议栈事件和按键事件来说明事件处理的过程。1.协议栈事件 29第三章MMI的研究与实现首先建立一个协议栈处理器。全局数组protocolEventHandler[]存储事件ID和对应的处理函数。无论哪个application调用SetProtocolEventHandler,对应的事件ID和回调函数都会加载到该数组中。该数组在开机初始化时已完成赋值。当收到消息后,函数ProtocolEventHandler()中调用的ExecuteCurrProtocolHandler()会在刚才的全局数组中寻找相应的事件ID。找到后再调用相应的回调函数,否则该事件被忽略。整个过程如图3.10:L4建立协议栈事件SetProtocolEventHandler()protocolEventHandler[]存储对应的eventID和entryFuncPtrPROTOCOL_MESSAGEMMI_Task()ProtocolEventHandler()ExecuteCurrProtocolHandler()回调函数clearClearprotocolEventHandler[]中存储的eventID和entryFuncPtrApplicationFramework图3.10协议栈事件流程2.按键事件首先建立一个按键事件。全局数组currKeyFuncPtrs[][]存储事件ID和对应的处理函数。无论何时调用函数SetKeyHandler,都会将对应的keycode、keytype、回调函数加载到该数组中。按键事件作为来自L4的协议事件,函数L4KeyHandle作为回调函数被调用。这个函数检测消息中的keycode、keytype,找到后再调用currKeyFuncPtrs[][]中的回调函数,否则该事件被忽略。整个过程如图3.11:ApplicationL4建立按键事件SetKeylHandler()currKeyFuncPtrs[][]存储对应的keycode、keytype和回调函数PROTOCOL_MESSAGE(KEY_EVENT)MMI_Task()ProtocolEventHandler()ExecuteCurrProtocolHandler()L4KeyHandle()ProcessKeyEvent()KeyEventHandler()ExecuteCurrProtocolHandler()回调函数clearclearcurrKeyFuncPtrs[][]中存储的keycode、keytype和回调函数Framework图3.11按键事件流程 29第三章MMI的研究与实现3.3.2历史管理前面说过,历史管理是对屏幕流的记录。我们可以把一个屏幕看作一个历史节点。它是以非缺省的堆栈(LIFO)形式实现的。启动的第一个屏幕被存储,而且不会从堆栈中移除。新的节点添加在堆栈的头位置。历史节点的数据结构如下:ScreenID(即将存储的屏幕ID)、EntryFunctionPoninter(重画屏幕)、InputBuffer(存储当前屏幕运行的文本数据)、GUIBuffer(存储当前屏幕的UI信息)。相关的应用有:添加节点到历史中、从历史中删除第N个节点、从历史中返回第N个节点、恢复一个屏幕的历史、恢复屏幕的InputBuffer、恢复屏幕的GUIBuffer、为调试清除历史、初始化历史。3.3.3OSL层前面说过,OSL层为系统提供了一个抽象封装,这使得MMI层有强适用性。它封装了两个核心对象:队列和计时器。与队列相关的API:1.创建队列oslMsgqidOslIntCreateMsgQ(PS8queue_name,U32max_msg_size,U32max_msgs);2.向队列写入信息OSLSTATUSOslIntWriteMsgQ(oslMsgqidmsgqid,void*msgPtr,U32msgSize,OSLWAITMODEwait_mode);3.从队列读出信息OSLSTATUSOslIntReadMsgQ(oslMsgqidmsgqid,void*msgPtr,U32*msgSize,OSLWAITMODEwait_mode);其中,queue_name是队列名,max_msg_size是消息的最大允许长度,max_msgs是队列中允许信息最大数。与计时器相关的API:1.开启计时器voidStartTimer(U16timerid,U32delay,FuncPtrfuncPtr);2.关闭计时器voidStopTimer(U16timerid);其中,timerid是计时器ID,delay是设定的延迟时间,funcPtr表示到达延迟时间时调用的函数。 29第三章MMI的研究与实现3.3.4NVRAMNVRAM其实就是按照一定组织结构在文件系统中划分的特定区域。主要面向预制的缺省出厂参数,以及用户在操作手机的时候存取的数据。如通讯录中在手机上存储记录就是按照一定的结构存储在NVRAM部分的,以及不同模块短信,照相摄像的设置信息,游戏记录分数等也是存放在NVRAM中的。优点是在读取这些参数的时候可以非常的快,不用考虑文件系统的影响。NVRAM管理器为协议栈提供了NVRAM读写接口。这些接口被用在不同的MMI应用,可以写数据或者从NVRAM上恢复数据。MMI可以在NVRAM中存储以下类型的数据:ByteData(1byte)、ShortData(2bytes)、DoubleData(8bytes)、ApplicationspecificRecord(Max2Kbytes)。用户自定义添加、删除一个数据项,或者调整一个缺省值,有以下五步:1.在头文件nvram_user_defs.h中的枚举变量nvram_LID_cust_enum中为新的逻辑数据项定义其LID2.在头文件nvram_user_defs.h中定义两个常量:SIZE和TOTAL3.在文件nvram_user_config.c中为该数据项定义缺省值4.在logical_data_item_table_cust[]中为该数据项定义各属性值5.在文件nvram_user_config.c中修改版本号CODED_DATA_VERSION6.编译例如:1.添加LIDtypeenum{NVRAM_EF_CUST_LID=NVRAM_LID_CUST_BEGIN,NVRAM_EF_PHB_SETTINGS_LID,/*新添LID*/……NVRAM_EF_LAST_CUST_LID}nvram_LID_cust_enum;2.定义SIZE和TOTAL#defineNVRAM_PHB_SETTINGS_SIZE20#defineNVRAM_PHB_SETTINGS_TOTAL13.定义缺省值statickal_uint8constNVRAM_PHB_SETTINGS_DEFAULT[NVRAM_PHB_SETTINGS_SIZE]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; 29第三章MMI的研究与实现4.定义属性值Itable_entry_structlogic_data_item_table_cust[]={……{NVRAM_EF_PHB_SETTINGS_LID,NVRAM_PHB_SETTINGS_SIZE,NVRAM_PHB_SETTINGS_TOTAL,NVRAM_PHB_SETTINGS_DEFAULT,NVRAM_ATTR_AVERAGE,/*定义属性*/NVRAM_CATEGORY_USER|NVRAM_CATEGORY_SHADOW,/*定义category*/"MP0i",/*添加文件前缀*/VER(NVRAM_EF_PHB_SETTINGS_LID),/*添加文件版本号*/"PhonebookSettings",NVRAM_RESERVED_VALUE}}5.修改版本号kal_uint8*CODED_DATA_VERSION=(kal_uint8*)""000.01B"";/*一般7个字节*/NVRAM的读写操作:S16pError;U8viewField[NVRAM_PHB_SETTINGS_SIZE];ReadRecord(NVRAM_EF_PHB_SETTINGS_LID,1,viewField,NVRAM_PHB_SETTINGS_SIZE,&pError);viewField[MMI_PHB_FIELD_EMAIL]=0;WriteRecord(NVRAM_EF_PHB_SETTINGS_LID,1,viewField,NVRAM_PHB_SETTINGS_SIZE,&pError);3.3.5文件系统文件系统的主要特性如下:1.处理许多物理或逻辑驱动2.支持三种FAT格式,media可在文件系统和其他操作系统之间交换分享数据 29第三章MMI的研究与实现1.支持长文件名,文件名最大可以255个字符,全路径最大可以260个字符2.支持UNICODE字体编码3.支持磁盘计算、FLASH、SRAM卡、硬盘4.支持有高效工作率的Cache5.支持多任务文件系统提供了兼容标准C的文件接口:FS_Open、FS_Close、FS_Read、FS_Write、FS_Seek、FS_Delete、FS_GetFileSize。为了给系统设计提供灵活性,更好的将应用层软件和物理设备驱动软件实现分割开来,降低应用层程序使用设备驱动的复杂性,提高应用设计和驱动设计的无关性,设计了应用层抽象模块。它位于系统应用层,为应用层模块提供文件操作的API接口。它通过OS提供的消息机制,请求文件服务器提供文件操作。文件服务器在OS的调度下,通过存储设备的驱动程序,最终完成数据在物理设备上的存储和读取。3.4UI层UI层的组件有类屏幕(categoryscreens)、UI元素、主题、图片、字体、绘图库如图3.7所示。类屏幕层封装了一组为应用提供界面的函数。它包含与应用相关的字符串ID和图片ID,提供了历史管理接口。每个类屏幕包括以下函数:显示函数(ShowCategoryXScreen)、退出函数(ExitCategoryXScreen),得到历史或历史大小函数。MTK提供几百种风格的类屏幕。UI元素层提供了各种UI元素(如按钮、滚动条、菜单)并显示出来。主题层基于UI元素提供了固定的样式设置。包括对象外形和颜色,字体类型和风格等其他属性。3.5Application层在应用层中所包括的模块很多,例如主菜单(IdleScreen)、通讯录(PhoneBook)、短信息(Messages)、通话记录(CallHistory)、通话管理(CallManagement)、设置(Setting)、娱乐游戏(Fun&Games)、工具箱(Organizer)、服务(Services)、音乐播放器(AudioPlayer)、摄相头(Camera)、图片编辑器(PhotoEditor)、录音机(SoundRecorder)等等。本节中将介绍如何写一个简单的Application(例如新来电)。第一步:初始化函数。在MMItask初始化函数InitializeAll()中调用InitIncomingCall[26][27]。定义函数InitIncomingCall时要初始化各种事件处理函数。 29第三章MMI的研究与实现voidInitIncomingCall(void){……SetProtocolEventHandler(psCBackCallIncoming,PRT_INCOMINGCALL_EVENT);SetHiliteHandler(MITEM_INC_OPT_ANSWER,HiliteMenuIncomingAnswer);……}第二步:组织资源数据。函数PopulateCmResData用于添加所需的UI资源。图片资源:宏ADD_APPLICATION_IMAGE2文字资源:宏ADD_APPLICATION_STRING2菜单项资源:宏ADD_APPLICATION_MENUITEMvoidPopulateCmResData(void){…ADD_APPLICATION_STRING2(STR_INC_ACT_OPT_PSEUDO,"IncomingCall“,”Stringtodisplayforincomingcall”);ADD_APPLICATION_IMAGE2(ICN_INC_HLD_OPT_IGN,"..\\IMAGES\\16x12\\NoImage.ppf“,”noimage);…}第三步:声明ID(屏幕、菜单项、字符串和图片ID)。第四步:进入和退出函数控制屏幕流。进入函数实现包括如下内容:1.执行当前的退出处理2.建立退出处理3.为当前的屏幕获取GUI缓冲器4.获取屏幕上显示的元素5.注册Highlight处理(Highlight处理函数通过设置左右软键通过实现)6.调用类函数绘制屏幕退出函数实现包括如下内容:1.建立历史节点2.在历史节点中存储进入函数3.在历史节点中填充输入缓冲器和GUI缓冲器4.存储历史 29第三章MMI的研究与实现图3.12可以形象地说明屏幕流操作(即进入/退出)在历史堆栈中的情况。Exit_A历史堆栈ABCBExit_BExit_CExit_BScreenId_AEntry_A历史堆栈ScreenId_AEntry_A历史堆栈ScreenId_BEntry_BScreenId_AEntry_A历史堆栈currExitFuncPtrEntry_BExit_AEntry_CExit_BGoBackHistoryExit_BTopApplication图3.12屏幕流操作3.6小结本章首先介绍了MTK平台的结构特色——KAL、L4适配层和MMI与协议栈L4的通信机制。由于本课题研究的是MTK平台应用层的软件设计,故重点分析了MMI层的软件结构。通过了解MMI的Task运行机制和其三大模块的相关功能及其之间的接口和交互,从而对应用层软件有了整体的认识。最后举例说明如何写一个application。本章的所有工作是针对下章通讯录应用具体实现而展开的。 55第四章通讯录应用的设计与实现第四章通讯录应用的设计与实现上一章节中曾列举了一些常见的Application,这些Application包括很多种,从是否和协议栈交互来分类来考虑,它们可以被分为:与协议栈交互和不交互的应用[28]。前者包括诸如通讯录、短信息、通话管理、蓝牙等应用,后者类似于计算器、游戏等基于平台而开发的小应用。通讯录应用和短信、通话管理应用一样,都是每部手机的最基本最重要的功能之一。由于其属于与协议栈交互的典型应用,且在这个设计与实现中涵盖了UI设计、平台消息分发、窗口绘制机制、历史管理机制等核心内容,因此本章以通讯录应用为例,详细说明手机应用软件的设计和开发过程。4.1初步设计与分析4.1.1系统需求分析依据通讯录应用模块的需求,从软件工程的角度对其进行系统分析和建模[29]:从功能上分析,通讯录需要实现读取、添加存储、删除、查找、复制、转存、设置等基本功能和其它功能(来电免打扰、快速拨号),如图4.1所示:图4.1通讯录基本功能用例图 55第四章通讯录应用的设计与实现从应用间的交互来分析,可以分为两种模式[30]:1.直接调用模式用户直接通过进入通讯录应用实现其基本功能,例如对电话条目的操作(查找、添加、删除、复制等)、设置等,还可以在直接向通话管理、短信息、安全密码应用等发出调用请求,被调用的模块即便不是在当前窗口也可通过专门的调用接口实现对其的操作,如电话条目的呼叫功能、发送短信息功能、是否输入保密码等操作。虽然这些调用给人在界面的感觉是直接完成的,但是这种操作是局部受限的,用户是不能使用被调用模块的其他功能。这种设计的好处是避免了应用交互可能出现的冲突。该模式用例图如下:图4.2直接调用模式用例图2.间接调用模式用户在进入其他应用中实现某功能的过程中,需要调用部分通讯录应用的功能。例如在短信息应用中,用户如果需要选择已有的电话条目时,就必须调用通讯录应用的读取、查找等相应操作。用户可以和界面直接互动,这也就是间接调用中的显式调用概念。相对地,也有隐式调用。例如在通话管理应用中,用户进行拨号或者处理新来电时,界面可以直接显示已经存储过的电话条目的用户名等信息。这些过程中都是需要先给通讯录发送相关的电话号码,通讯录应用会在缓冲区内进行号码匹配,然后把匹配后的条目的其他信息返回给之前的应用模块。这一过程对于用户而言是不可见的。该模式用例图如下: 55第四章通讯录应用的设计与实现图4.3间接调用模式用例图本项目中,关于通讯录应用和其他应用模块的交互实现也是设计的重点之一。从界面显示来分析,两种手机平台是有很大的不同的。首先,MTK平台所有应用的一级菜单项和其子菜单项的列举都是在同一个界面中的纵向显示。用户进行选择时,依靠键盘上下键和滚动条上下操作,这是界面上呈现出来的效果。然而,某款手机所应用Symbian平台中一、二级菜单项的列举都是不同界面切换和横向显示的。用户进行选择是靠键盘的左右键。由于其中涉及的实现机制和UI修改等,对于其他应用而言也都是通用的,故在进入所有应用之前设计了通用的接口函数完成了界面的调整。其次,进入通讯录应用后,小到GUI控件、大到整个category,还有屏幕流管理,都需要重新布署设计。基于上述用户需求分析可知,通讯录应用的软件设计组成如图4.4所示:通讯录应用其他应用界面显示功能实现图4.4通讯录应用软件设计组成4.1.2模块设计思路1.MMI通讯录应用对应的目录: 55第四章通讯录应用的设计与实现lcmmimmiPhoneBooklcmmimmiPhoneBookPhoneBookInclcmmimmiPhoneBookPhoneBookSrc对应的文件:PhoneBookDef.h(声明屏幕、字符串和图片的ID)PhoneBookGprot.h(与其他应用交互相关的函数声明)PhoneBookProt.h(基本功能函数的声明)PhoneBookTypes.h(定义了重要的宏、结构体、枚举变量)PhoneBookMain.c(进入通讯录应用和电话列表的相关API)PhoneBookOperateSingle.c(针对单条电话条目操作的所有API)PhoneBookOperateMass.c(针对单条电话条目操作的所有API)PhoneBookSearch.c(关于查找功能的所有API)PhoneBookCallerGroups.c(关于群组功能的所有API)PhoneBookExtraNumber.c(关于使用其他号码功能的所有API)PhoneBookSettings.c(关于设置功能的所有API)PhoneBookStubsToOthers.c(与其他应用交互的所有API)开发人员可以根据以上已有的代码结构进行分析和二次开发。2.全局变量通讯录中,在文件PhoneBookTypes.h定义了一个重要的结构体:mmi_phb_context_structg_phb_cntx;该结构体中含有很多成员,标识通讯录的一些状态标志,比如全局的矩阵型指针,系统设置,列表的索引等等变量。3.数据结构[31]A.常量与枚举变量常量:文件phb_defs.h中定义了一些通讯录应用相关的宏,比如SIM卡或者手机上存储的电话条目最大值,查找时输入字符串长度最大值,存储条目的姓名或号码的长度最大值等等。枚举变量:在PhoneBookTypes.h中定义了很多枚举变量,比如变量MMI_PHB_STORAGE_LOCATION里面列举了存储类型(手机或者SIM卡存储)。在TimerEvents.h中变量MMI_TIMER_IDS定义了几个与通讯录应用相关的计时器ID值。B.内部数据结构例如结构体PHB_OPTIONAL_IDS_STRUCT用于记录每一个存储在手机上的电话条目的图片ID、铃声ID、分组ID。C.外部数据结构[32] 55第四章通讯录应用的设计与实现例如l4c2phb_struct.h中定义了结构体phb_entry_struct,它包含所有存储的电话条目的基本属性,包括索引、存储类型、bcd编码格式的电话号码等。4.相关接口通讯录应用为L4C提供了处理所有电话号码的函数,同时它也支持在SIM卡或者NVRAM上存储电话号码相应的数据。因此,通讯录应用有个和上层L4C的接口和下层SIM与NVRAM的接口。其中,L4C与通讯录的入口就是PHB_L4C_SAP,通讯录和SIM与NVRAM的入口分别是PS_SIM_SAP、PS_NVRAM_SAP。上述关系的结构图如下:L4ControllerPHBSIMNVRAMPHBKernelPHBSearchEngineIndexBuilderRetrivalProcessorinternalindexstructurePS_NVRAM_SAPPS_SIM_SAPPHB_L4C_SAP图4.5相关接口关系结构图5.初始化通讯录应用首先在MMITask.c里增加对通讯录应用的初始化:voidInitializeAll(){......PopulateResData();/*加载所有的资源数据*/......mmi_phb_protocol_event_init();/*通讯录应用的初始化*/InitCallManagement();/*通话管理应用的初始化*/......} 55第四章通讯录应用的设计与实现函数PopulateResData中又调用了PopulatePbResData,加载了通讯录应用的相关资源。6.添加新资源需要添加的新资源有字符串资源、图片资源、菜单项和菜单组资源。将资源先添加到PhoneBookDef.h文件中对应资源的枚举变量里,用前面介绍的宏在Res_PhoneBook.c中加载新资源,其中该文件中还注册了相应菜单项对应的Highlight事件。4.2初始化详细流程设计下面是通讯录中最重要的结构:MMI_PHB_ENTRY_BCD_STRUCTPhoneBook[MAX_PB_ENTRIES];PhoneBook[]是存储通讯录电话条目的数组,大小为手机的容量和SIM卡容量总和。但是这个数组的内容并不是连续的。图4.6说明了电话条目的物理存储位置和数组PhoneBook的存储位置之间的对应关系:图4.6电话条目的存储位置其中,record_index是entry的物理存储位置,从1开始。store_index是entry在数组PhoneBook中的存储位置,从0开始。在初始化的工作中,MMI完成了从电话条目的物理存储位置到数组PhoneBook中的存储位置的映射。上一节介绍过通讯录应用初始化函数InitializeAll(),当MMItask被创建时调用InitializeAll(),它先初始化Framework,NVRAM数据,然后才初始化各应用。通讯录应用的初始化函数mmi_phb_protocol_event_init()中初始化相关的全局变量g_phb_cntx和指定消息的处理函数:voidmmi_phb_protocol_event_init(void) 55第四章通讯录应用的设计与实现{SetProtocolEventHandler(mmi_phb_ind_startup_finish,PRT_PHB_STARTUP_FINISH_IND);SetProtocolEventHandler(mmi_phb_ind_startup_begin,PRT_PHB_STARTUP_BEGIN_IND);SetProtocolEventHandler(mmi_phb_ind_startup_read,PRT_PHB_STARTUP_READ_IND);......g_phb_cntx.start_scr_id=0;g_phb_cntx.end_scr_id=0;......}下面详细的从函数调用和消息传递的角度来叙述通讯录应用的初始化设计全过程,图4.7介绍了初始化的消息之间的传递过程:MMI/RMMIL4ControllerPHBL4CPHB_START_REQL4CPHB_STARTUP_READ_INDPRT_PHB_STARTUP_READ_INDPRT_PHB_STARTUP_READ_NEXT_INDL4CPHB_STARTUP_READ_NEXT_INDL4CPHB_STARTUP_CNFPRT_PHB_STARTUP_FINISH_INDSIM/NVRAMnvram_get_info()NVRAM_EF_PHB_LIDsim_service_table_query(EFAND,EFFDN,EFBND,EFMSISDN,EFSND,…)SIM_READ_REQNVRAM_READ_REQSIM_READ_CNFNVRAM_READ_CNFReadyPRT_PHB_STARTUP_BEGIN_IND图4.7初始化的消息传递1.L4在到NVRAM读取data之前,发送消息到MMI:PRT_PHB_STARTUP_BEGIN_IND。进入回调函数mmi_phb_ind_startup_begin()中,初始化设置了一些变量,准备载入entries(电话条目)。2.L4每读取一个ADNentry(存储在SIM卡中的电话条目),都有发送消息PRT_PHB_STARTUP_READ_IND到MMI,其中L4返回消息结构体为: 55第四章通讯录应用的设计与实现mmi_phb_startup_read_ind_struct。函数mmi_phb_ind_startup_read接收从L4发过来的开始读取消息:PRT_PHB_STARTUP_READ_IND。然后MMI再发消息到L4请求读取下一条:PRT_PHB_STARTUP_READ_NEXT_REQ。不管是读取存储在SIM还是NVRAM的entry,函数mmi_phb_startup_read_entry把所有entries数据存储在MMI中全局变量PhoneBook[store_index]里。可见PhoneBook[]中的存储顺序就是L4中的存储顺序。PhoneBook[store_index].tel.number中保存的是ASCII码,根据号码的第一个位置来设置是SIMentry还是NVRAMentry。姓名列表g_phb_name_index[]保存的是PhoneBook中entry的位置。它的结构如下:MMI_PHB_ENTRY_BCD_STRUCTPhoneBook[MAX_PB_ENTRIES];typedefstruct{MMI_PHB_NUMBER_BCD_STRUCTtel;//电话号码MMI_PHB_NAME_STRUCTalpha_id;//联系人姓名}MMI_PHB_ENTRY_BCD_STRUCT;结构体成员tel的类型MMI_PHB_NUMBER_BCD_STRUCT数据结构如下:typedefstruct{U8type;U8length;U8number[(MAX_PB_NUMBER_LENGTH+1)/2];}MMI_PHB_NUMBER_BCD_STRUCT;//电话号码的类型、长度、内容结构体成员alpha_id的类型MMI_PHB_NAME_STRUCT数据结构如下:typedefstruct{U8name_length;U8name_dcs;U8name[(MAX_PB_NAME_LENGTH+1)*ENCODING_LENGTH];}MMI_PHB_NAME_STRUCT;//联系人姓名的长度、编码格式、内容3.当L4从NVRAM中读取完之后,发送消息到MMI:PRT_PHB_STARTUP_FINISH_IND,表示L4已经读完了。MMI接收到这个消息之后,开始从L4中载入所有的entries。其中L4返回消息结构体为: mmi_phb_startup_finish_ind_struct。函数mmi_phb_ind_startup_finish接收到消息: 55第四章通讯录应用的设计与实现PRT_PHB_STARTUP_FINISH_IND后,初始化g_phb_cntx中的结构,从NVRAM中读取电话条目的一些信息(比如:群组,栏位设置,存储选择等),开始排序。其中的函数mmi_phb_sort_build_name_index使PhoneBook中所有entries,都是按照g_phb_name_index[]中的值顺序排列的,也就是按照姓名中字母从小到大的顺序。g_phb_name_index[]中存储的是PhoneBook[]中entries的存储索引,这个函数的过程就是通过它存储的值,找到PhoneBook中相应的entries,然后比较PhoneBook中entries的name,从而来排列g_phb_name_index的值。所以显示的电话列表并不是按照PhoneBook[]的0,1,2等顺序来的,而是按照g_phb_name_index[]的0,1,2等顺序来的。当FDN(SIM卡存储的固定拨号)启动之后,为了防止未授权拨号,ADN就不能从SIM卡中读取出来了。把FDNlist拷贝到ADN的存储区,发送消息:PRT_PHB_GET_ENTRY_BY_INDEX_REQ到L4,去读取FDN。返回消息:PRT_PHB_GET_ENTRY_BY_INDEX_RSP。然后再进入回调函数:mmi_phb_fdn_get_list_to_ram_rsp中,把读取的信息保存到PhoneBook[store_index]中。可见,PhoneBook是先保存NVRAM号码,然后是SIM号码。当获取到FDNlist之后,一定要获取speeddialnumber。函数PhbReadSpeedDialNVRAM从NVRAM中读取速拨信息后,开始建立lookuptable。函数mmi_phb_init_build_lookup_table把PhoneBook中以g_phb_name_index[]中的内容为索引的entry的号码,转换成ASCII码,然后转换成32为int型数据,并保存在全局变量LookUpTable[]中,一并保存的还有store_index也就是该entry在PhoneBook中存储位置。500ms之后,定时器溢出,进入函数:mmi_phb_init_populate_lookup_table中。它以g_phb_name_index[]中的内容为索引,到NVRAM中读取optionfields数据ReadMultiRecord()。然后把读取的数据保存在LookUpTable[]中。包括传真号码,家庭号码,公司号码等。每读取10次,就暂停250ms,然后继续读取。全部读完之后,进入mmi_phb_lookup_table_sort。因为在装载电话号码的时候,LookUpTable[]中的内容是按照字母顺序装载的,但是装载NVRAM中的传真,家庭,公司号码等时,是按照存储顺序装载的。而这里的排序,是根据电话号码的大小来排序的。即按照电话号码的大小,从小到大排列。当来电或者短信息的时候,采取对半查找来完成号码快速匹配姓名,效率就很高了。综上所述,通讯录的初始化步骤如下:1.从NVRAM,SIM卡中读取了数据,并保存在L4中;2.MMI中的全局变量PhoneBook[]与L4中的通讯录实现同步;3.g_phb_name_index[]中按照字母的大小顺序,记录了每一个entry在PhoneBook[]中的存储位置; 55第四章通讯录应用的设计与实现4.所有的号码,包括存在于SIM卡和NVRAM上的所有移动电话、家庭、公司、传真号码等,都按照大小顺序存储在LookUpTable[]中了,并且存储在PhoneBook中的存储位置索引。4.3界面显示的设计与实现4.3.1一、二级菜单设计高仿某款手机的一、二级菜单项的选择方式,从界面上看是靠左右键横向切换。一级菜单就是从主菜单界面进入所有应用的菜单,MTK平台一般都是九宫格的模式。根据这个窗口的显示风格,写一个新的类屏幕函数,例如ShowNokiaCategory。用户进入已有的goto_main_menu后,调用ShowNokiaCategory就能显示预期的屏幕。所有进入下一级菜单项的函数都列在ShowNokiaCategory中。每个菜单项都对应唯一的索引值index,当用户选择好了准备进入的应用时,该函数就根据nokia_current_index将左软键回调函数设成菜单项相应的入口函数。可以把这个设计思路用在进入各应用后的菜单列表上,也就是之前说的二级菜单,其实对于应用本身而言是应用的一级菜单。进入各应用自己的模块后调用属于自己的ShowXNokiaCategory达到预定的显示效果。本人负责编写的通讯录应用中,在进入二级菜单界面的入口函数mmi_phb_entry_main_menu时,调用函数ShowPhbNokiaCategory。先列出重要的变量:A.记录菜单index:phb_current_index、phb_next_index、phb_pre_indexB.记录菜单图标位置:phb_current_x、phb_current_y、phb_pre_x、phb_pre_y、phb_next_x、phb_next_yC.记录当前子菜单和图标:phb_image[]、phb_item[]D.记录总的菜单个数:phb_total、phb_item[]函数ShowPhbNokiaCategory主要的任务流程:1.在phb_image[]、phb_item[]保存通讯录中所有一级菜单项对应的图片和字符串,并依据phb_current_index值显示当前的菜单项名称。2.依据固定的坐标用GDI绘出左右控键和phb_current_index值所指的菜单项图片。3.依据phb_current_index值更改左右软键的回调函数,这里列出了通讯录应用下的七个一级菜单项的入口函数。4.设置上下左右键的按键处理函数(key 55第四章通讯录应用的设计与实现handler)。除了要考虑每个情况下GUI控件坐标、图片、字符串等问题,还要考虑先后的键盘事件是否相同并启动计时器,这样才能保证用户随意切换左右按键时不会出错。一级菜单和二级菜单的界面如图4.8所示:一级菜单二级菜单图4.8一、二级菜单界面设计4.3.2编辑框的设计因为平台的不同,其中的编辑框、输入法、输入限制等要求不一定一样,要严格按照用户要求去设计。在通讯录应用中,有很多地方都需要调用这个界面。例如新建条目编辑姓名和号码时,或者修改当前条目姓名和号码时。我们现仿造MTK平台中的类函数来创建自己需要的类函数ShowCategory5Screen_nokia、RedrawCategory5Screen_nokia和ExitCategory5Screen_nokia。首先,由于本应用中很多操作都可能调用这个类函数,所以我们可以在这些调用的地方设置相应的flag(例如:flag_add_name/flag_edit_name/flag_inputbox)去避免影响其他操作的正常调用。根据语言的设置,编辑的界面有所不同,比如文字、控件、坐标、输入法等等就必须分情况考虑了。首先介绍下MTK的类屏幕设计,下面是它的基本流程[33]:1.获取窗体模版的ID2.根据模版的ID得到组件的集合和个数3.根据模版ID得到组件属性标识的集合4.锁定当前的frame,各个组件绘制前的任务准备就绪5.绘制窗体之前,还可以调整窗体的大小6.获取不同组件的不同属性,并根据不同的属性绘制出自己需要的窗口7.全部绘制完毕,整合GDIlayer,将当前frame解锁在本次绘制自己需要的窗口中,设计的重点就是编辑框。在函数:ShowCategory5Screen_nokia中调用的wgui_setup_inputbox完成了编辑框的建立和显示。如果是输入内容超出一行的话,可以把输入框性质设置为多行输入: 55第四章通讯录应用的设计与实现EDITOR_MULTILINE_INPUT_BOX。首先通过判断语言模式来设定输入模式,创建多行输入的buffer和注册按键事件(左右键使光标向前或后移动,可以在光标移到的位置上进行编辑)等。当用户开始在编辑框中输入信息时,共用体MMI_multiline_dailer_inputbox_union.MMI_multiline_inputbox中存放了文本内容。每次当前编辑框进行修改时,都会调用wgui_handle_inputbox_input。因为它是函数wgui_setup_inputbox中注册的对编辑框进行操作时设置的回调函数。由于编辑框里可能更换输入方式、正在编辑文本内容,或者修改的时候将文本清空,或者文本到了最大限制数时,左右软键的操作和显示都是不同的。这个回调函数和函数wgui_set_RSK根据以上各种情况,满足了所有条件下的应变操作。其他函数如:RedrawCategory5Screen_nokia()是屏幕的刷新函数;ExitCategory5Screen_nokia()是屏幕的退出函数。图4.9是姓名查找时显示的编辑框界面:图4.9编辑框界面设计4.3.3弹出窗口的设计在用户进行某一操作时,手机界面都会有个弹出窗口,上面可能有操作名称的显示、操作的动画图片、操作成功与否的提示,有时还播放对应的声音。弹出窗口属于频繁更新的界面,对于某些一直不变的显示元素,可以提取出来画到一个模拟的屏幕中,而将一些需要更新的元素画到另外的模拟屏幕,而后将两个模拟屏幕合并到真正的屏幕上,这样我们就节省了不变元素的重画时间,从而减轻了系统负担及加速画面更新。我们把这样的模拟屏幕就叫层,也可以说层就是屏幕的缓冲空间。 55第四章通讯录应用的设计与实现如果用动画做为背景,将其他的一些元素也画到这一层中,就会出现当动画跳到第二帧后,动画上面的文本及图象都会被盖住。而有了层以后,我们就可以将不变的文本及图象放到新建的一个层中,将动画放到背景层中,每当有动画换帧时,只需将新帧画到背景层中,然后合并两个屏幕(动画刷新时会自动合并),这样上层的文本等就不会被盖住了。另外,因为层的格式简单且统一,并且一般的图形系统都会用硬件加速合并,所以在层合并时加上些特效会很方便,如通透、半透明、剪切等。在MTK平台中函数DisplayPopup就是弹出窗口的实现函数。根据平台间的差异性,我们建立自己的弹出窗口函数:DisplayNokiaPopup和PopupNokiaTimerOver。前者有五个相关参数:显示的字符串、图片ID、图片是否在按钮上、延迟时间、提示音。后者是计时器的调用函数,它执行关闭计时器和播放声音,并调用GoBackHistory。前者又涉及到新窗口的绘制问题,同样的,我们建立自己的函数ShowNokiaCategory65Screen,它下面调用的ShowNokiaCategory401Screen才开始绘图。首先要确定弹出窗口的坐标和各控件的坐标和需要显示的图片、字符串。以下是建立多层屏幕的过程[34]:1.函数gdi_layer_multi_layer_enable开启多层2.创建层:创建层需要先建一个层句柄,我们可以通过该句炳来控制层,函数gdi_layer_create用来创建层:gdi_layer_create(OFFSET_X,OFFSET_Y,WIDTH,HEIGHT,HANDLE_PTR);其中,OFFSET_X,OFFSET_Y是层的位置坐标,WIDTH,HEIGHT是层的大小,HANDLE_PTR是层句炳,用于返回所创建的层。不过,因为创建层时系统要为其分配动态内存空间,而系统保留的内存一般只够创建一个UI_device_width×UI_device_height大小的层,所以如果已有两个层,而需要再创建新层时,就需要用到函数:gdi_layer_create_using_outside_memory(X,Y,WIDTH,HEIGHT,HANDLE_PTR,OUTMEM_PTR,OUTMEM_SIZE)前五个参数和gdi_layer_create的参数相同,OUTMEM_PTR是存放层的BUFFER,OUTMEM_SIZE是层的大小。3.激活层:任何时刻有且只能有一个层处于激活状态,所有的绘画都会默认画到这个激活层中,所以想要在层上绘画必须先将其激活。激活函数是:gdi_layer_set_active(gdi_handlehandle);不过,由于在多层的处理中需要在各个层之间切换激活,所以我们经常用到的是:gdi_layer_push_and_set_active(gdi_handlehandle);此函数会把当前的激活层入栈而激活参数层,等到下次需要激活栈中的层时,只需要用函数gdi_layer_pop_and_restore_active激活就可以了。4.基础层:系统开机的时候会为每个硬件屏幕创建一个基础层,它由系统创建,无法删除。存储于芯片内的flash中,故绘画极快,一般我们会将刷新频繁的内容放在基础层上。5.合并所有层:函数gdi_layer_blt_previous和gui_BLT_double_buffer具有同样的效果。在合并前,我们需要用函数gdi_layer_set_blt_layer来指明需要合并的层。 55第四章通讯录应用的设计与实现6.释放:由于空间的问题,我们创建的新层在用完后一定要释放,释放函数是:gdi_layer_free。根据层的几个特效(剪切、通透、透明、锁屏),可以更好的完善整个设计效果。图4.10是删除电话条目时弹出的纯静态和动态提示窗口的界面:纯静态弹出窗口动态弹出窗口图4.10弹出窗口界面设计4.3.4窗口绘制与History管理设计不仅是前面三个的设计和窗口设计相关,每个菜单项都对应一个窗口入口函数,它可以绘制子菜单项,注册Highlight事件、按键事件,可以保存上一个窗口和当前窗口的内容等等。这时引来另外一个问题,就是关于窗口切换是通过什么来实现的,怎么才能保证这些窗口在切换的过程中保持当时的状态。这就涉及到History管理。下面将介绍它们的设计过程。A.窗口绘制机制窗口的进入都是通过形如这种:mmi_phb_entry_*()来实现的。它的步骤如下:1.保存前面那个窗体的内容2.获得足够的缓存空间来保存当前要显示的窗体的内容3.获得下一个要显示的窗体的属性4.获取要显示的子菜单条目的个数5.设置要被显示的新窗体的父窗体6.设置下一级子菜单要被高亮显示的条目7.设置按下左右软件的执行函数8.设置退出下个窗体的的调用函数这些工作一般都在窗体的入口函数里面实现的内容,因此,我们有必要先从窗体的入口函数开始。以一段代码来说明(这里省略了很多的东西):voidmmi_phb_entry_setting(void) 55第四章通讯录应用的设计与实现{//1.退出上一窗口,进入新的窗口EntryNewScreen(SCR_PBSETTINGS_LIST,mmi_phb_exit_setting,mmi_phb_entry_setting,NULL);//2.获取当前窗口的GUIbufferguiBuffer=GetCurrGuiBuffer(SCR_PBSETTINGS_LIST);//3.获取列表窗口的子菜单数目nNumofItem=GetNumOfChild(MITEM110_PBOOK_SETTINGS);//4.获取要显示的字符串序列GetSequenceStringIds(MITEM110_PBOOK_SETTINGS,nStrItemList);//5.设置当前窗口的父窗口的IDSetParentHandler(MITEM110_PBOOK_SETTINGS);//6.注册highlight函数RegisterHighlightHandler(ExecuteCurrHiliteHandler);//7.在已经获取了以上信息后,绘制当前的窗口ShowNokiaScreen(STR_ID_FNG_NOKIA_SETTING,IMG_SCR_PBOOK_CAPTION,STR_GLOBAL_SELECT,IMG_GLOBAL_OK,STR_GLOBAL_BACK,IMG_GLOBAL_BACK,nNumofItem,nStrItemList,value,5,flag,func,guiBuffer);//8.后面是注册按键函数SetRightSoftkeyFunction(GoBackHistory,KEY_EVENT_DOWN);}B.History管理机制与EntryNewScreen1.与EntryNewScreen函数有关的全局变量currEntryFuncPtr、currExitScrnID、currTopScrnID、currExitFuncPtr 55第四章通讯录应用的设计与实现2.EntryNewScreen函数流程(1)保存新屏幕ID(函数第一参数):currTopScrnID(2)调用ExecuteCurrExitHandler(3)保存新屏幕ID:currExitScrnID(4)调用SetGenericExitHandler(5)返回值MMI_TRUE3.函数ExecuteCurrExitHandler依次调用了ExecuteCurrExitHandler_Ext、ClearInputEventHandler。前者在不清除按键事件条件下执行当前退出函数句柄,后者清除当前窗口注册的按键事件。4.函数SetGenericExitHandler将函数EntryNewScreen中的几个参数传递给全局变量,留待下次调用它时使用。5.牵涉到的退出函数voidmmi_phb_exit_setting(void){//将当前的屏幕ID赋值给全局变量(通讯录应用中当前的历史节点)g_phb_cntx.end_scr_id=SCR_PBSETTINGS_LIST;}综上所述,EntryNewScreen函数先将上次执行EntryNewScreen时记录的currEntryFuncPt、currExitScrnID以History结构为载体记录入栈。然后执行退出函数。最后将本窗口的scrnID、exitFuncPtr、entryFuncPtr存入全局变量,留待下次调用EntryNewScreen时使用。4.4核心功能的设计与实现4.4.1显示电话号码列表前面介绍的通讯录初始化流程,可以看出通过消息传递将对所有电话条目完成读取并排序。如果初始化成功,我们就可以进入通讯录应用了。进入电话号码列表方式很多,不一定非要通过查找才能进入。枚举变量MMI_PHB_LIST_VIEW罗列出各种情况,如果是通过本身应用调用进入的话,此时:MMI_PHB_LIST_VIEWphbListViewphbListView==MMI_PHB_LIST_FOR_PHB; 55第四章通讯录应用的设计与实现这种情况下就调用函数mmi_phb_list_pre_entry(其他应用就调用另外一个函数,后面有介绍)。不管何种方式都会调用真正显示列表的函数:mmi_phb_entry_list。它在进入列表前会判断全局变量PhoneBookEntryCount值是否为零(所有电话条目记录为空)。如果没有记录,则会出现弹出窗口提示记录为空,退回前一屏幕的状态。这个过程比较容易实现,下面我们重点设计和实现如何显示含记录的列表屏幕SCR_PBOOK_LIST。mmi_phb_entry_list(PhoneBookEntryCount,/*电话条目的总和*/STR_GLOBAL_OPTIONS,/*左软键显示字符串*/IMG_GLOBAL_OPTIONS,/*左软键显示图片*/mmi_phb_get_index,/*高亮回调函数*/mmi_phb_entry_op_option,/*左软键回调函数*/mmi_phb_choose_number_normal,/*SEND键回调函数*/mmi_phb_list_get_item,/*获取所有entries的item函数*/mmi_phb_list_get_hint,/*Hint回调函数*/mmi_phb_list_pre_entry,TRUE,TRUE);/*标识方向键中右键是否有注册按键事件*/上面注册的函数完成各功能如下:1.高亮函数mmi_phb_get_index():完成设置g_phb_cntx.active_index。它是在数组g_phb_name_index[]中的位置:0,1,2,3,……。即当前高亮的entry在数组g_phb_name_index[]中的顺序位置。2.左软键响应mmi_phb_entry_op_option():进入每一个entry的选项菜单,里面是针对当前条目进行的各种操作。3.SEND键响应mmi_phb_choose_number_normal():当该entry有多个号码时,可以让用户选择拨哪个号码。4.获取SIM卡item:mmi_phb_list_get_item()。获取entry对应的姓名,没有姓名的就获取号码。5.hintcallback:mmi_phb_list_get_hint_sim()。获取hint信息。函数mmi_phb_entry_list中调用了mmi_phb_list_build_alpha_index(),这是一种用户快捷方式。按照g_phb_name_index[]中保存的字母顺序,提取PhoneBook中的姓名,按照首字母的顺序以26个字母为索引,把每个entry在电话列表中的listindex保存在g_phb_alpha_index_list[]中。即g_phb_alpha_index_list[]中保存的是该entry的listindex。这样,当用户输入某个字母时,如“c”,那么就可以直接跳转到g_phb_alpha_index_list[2]的值所指示的位置。 55第四章通讯录应用的设计与实现在显示电话号码列表时,也就是显示动态的LIST。从g_phb_name_index[]中取出每个entry在PhoneBook[]中的store_index,然后获取PhoneBook[]中的姓名,转载到subMenuData[]中,最后拷贝到MMI_fixed_icontext_menuitems[]。绘屏的类屏幕函数是ShowCategory184Screen和RedrawCategory184Screen,后者调用的show_dynamic_list中读出MMI_fixed_icontext_menuitems[]中的值,最终实现了列表显示,并在类函数中设计实现了所涉及到的所有UI元素。4.4.2添加新条目新添一条记录是最基本的功能,用户可以根据存储方式的设定存储到手机或者SIM卡上。本项目中的每条记录都可以存储很多其他信息,要求包括姓名、号码、头像、铃声等等。在进入添加入口函数之前先判断存储是否达到最大值,如果是就弹出窗口提示“存储已满”,否则开始添加新条目。添加的顺序是先姓名后号码,只要有一个记录不为空,最后都能将信息存入一个entry,根据设置过的存储类型(g_phb_cntx.prefer_storage)准备给L4发送保存的请求。当然在发送消息之前,函数mmi_phb_op_add_entry_req里面首先要把本地参数缓冲区分配出来,完成了消息结构体的赋值后送到外部队列。整个流程如图4.11所示:MMIL4ControllerPHBSIM/NVRAMAddphysicalrecord(NVRAM_EF_PHB_LID,EFAND,EFFDN,EFBND,EFMSISDN,EFSND,…))PHBReadyCheckemptyornotPRT_PHB_SET_ENTRY_REQPRT_PHB_SET_ENTRY_RSPL4CPHB_WRITE_CNFL4CPHB_WRITE_REQ4CPHB_WRITE_REQmmi_phb_op_increase_lookup_tablemmi_phb_lookup_table_sortUpdatephblistindexmmi_phb_op_add_entry_reqmmi_phb_op_add_entry_rsp图4.11添加新条目的流程其中,在MMI中发送添加电话条目消息的请求和回复的结构体分别为mmi_phb_set_entry_req_struct、mmi_phb_set_entry_rsp_struct。下面列举出回复中结构体:typedefstruct{LOCAL_PARA_HDR 55第四章通讯录应用的设计与实现l4c_result_structresult;kal_uint16no_list;l4c_phb_entry_structlist[PHB_MAX_PHB_ENTRIES];}mmi_phb_set_entry_rsp_struct;结构体成员result的类型l4c_result_struct数据结构如下:typedefstructl4c_result_struct{kal_uint8flag;//值为0表示添加成功,否则失败kal_uint16cause;}l4c_result_struct;结构体成员list[]的类型l4c_phb_entry_struct数据结构如下:typedefstruct{kal_uint8storage;//条目存储类型kal_uint8type;kal_uint16index;kal_uint16record_index;l4c_number_structtel;//号码类型、长度、内容l4_name_structalpha_id;//姓名长度、格式、内容}l4c_phb_entry_struct;在函数mmi_phb_op_add_entry_req中,还注册了添加成功后L4返回MMI的消息PRT_PHB_SET_ENTRY_RSP的回调函数:mmi_phb_op_add_entry_rsp。当添加存储结果成功后,首先调用mmi_phb_op_increase_lookup_table把新的条目加入LookupTable中,然后调用mmi_phb_lookup_table_sort排序,更新通讯录列表的索引值。另外,发送请求的消息结构体中除了说明已设定的存储类型(NVRAM/SIM),还要说明条目类型(普通电话号码、FDN、机主号码、SDN等等)。如果直接在电话列表中添加条目的话,则对应修改FILE_ADN_IDX或NVRAM_EF_PHB_LID;如果是在“设置”中添加机主信息时,则对应修改FILE_MSISDN_IDX;如果要添加最近一次拨号操作记录,则对应修改NVRAM_EF_PHB_LN_ENTRY_LID。4.4.3删除已有条目 55第四章通讯录应用的设计与实现这里所说的删除已存电话条目的所有信息,并不是指实质意义上的删除。实体存储区的大小是固定不变的,我们所做的删除操作要在排序列表中使得该条记录不再显示,保证各条记录之间的前后相对排序关系不发生变化。而实际存储器中则是通过获取要删除的记录ID,给记录内容赋零值。准备删除前会有确认提示和铃音警告,为避免用户误操作而设置的。高仿某款手机的删除有三种,分别是单条删除、全部删除、逐条删除。后两个从功能上来讲,其实可以看作是单条删除动作的多次执行。界面上主要是设计屏幕及其History管理。下面就以单条操作为例介绍删除功能的设计与实现,整个流程如图4.12所示:MMIL4ControllerPHBSIM/NVRAMPhbUpdateSpeedDial()deletephysicalrecord(NVRAM_EF_PHB_LID,EFAND,EFFDN,EFBND,EFMSISDN,EFSND,…)UserdeleteanentryPRT_PHB_DEL_ENTRY_REQPRT_PHB_DEL_ENTRY_RSPL4CPHB_DELETE_CNFL4CPHB_DELETE_REQmmi_phb_op_clear_lookup_table_by_indexmmi_phb_lookup_table_sortUpdatephblistindexmmi_phb_op_delete_entry_reqmmi_phb_op_delete_entry_rsp图4.12删除已存条目的流程发送请求之前,先确定当前entry所在存储区的index值和存储类型:store_index=g_phb_name_index[g_phb_cntx.active_index];storage=(store_index>=MAX_PB_PHONE_ENTRIES)?MMI_SIM:MMI_NVRAM;myMsgPtr=(MSG_PHB_DELETE_ENTRY_REQ_STRUCT*)OslConstructDataPtr(sizeof(MSG_PHB_DELETE_ENTRY_REQ_STRUCT));myMsgPtr->index=(storage==MMI_SIM)?(store_index+1)–MAX_PB_PHONE_ENTRIES:(store_index+1);最后一个语句是说算出记录在实际存储区中相应的index值,因为这并不是当前g_phb_name_index[]中的index值。在MMI中,发送单条删除的请求和接收已删除回复的消息结构体是mmi_phb_del_entry_req_struct和mmi_phb_del_entry_rsp_struct。和上一节的添加操作对应的两个消息结构体定义类似,这里就不再列举。只是在结构体mmi_phb_del_entry_req_struct中多了一个结构体成员del_all,标识是否为多条操作。 55第四章通讯录应用的设计与实现当操作的条目物理删除成功后,调用函数mmi_phb_op_delete_entry_rsp。它是函数mmi_phb_op_delete_entry_req给消息PRT_PHB_DEL_ENTRY_RSP注册的回调函数。这个回调函数首先调用PhbUpdateSpeedDial函数,更新了快速拨号的table。根据已删条目的存储类型,修改全局变量g_phb_cntx.sim_used或g_phb_cntx.phone_used的值等。函数mmi_phb_op_clear_lookup_table_by_index从LookupTable中删除了被操作的entry。成功后调用mmi_phb_lookup_table_sort再次排序,更新列表索引值。4.4.4姓名查找通讯录的查找功能是衡量其设计水平和性能优劣的一个重要标准。它的考察指标主要是看搜索速度和查找结果。有的手机通讯录查找功能设计不太合理,存入的电话条目对应的联系人排列顺序混乱。既不是按拼音顺序排列,也不是按笔划排列。当用户每次查找的时候,都必须从第一个存储条目开始顺序查起,低效率给用户带来很多不便。而高仿某款手机的强大的查询能力被众多用户所青睐,本项目从这一方面为出发点开发出难度较低的首字母查询法。这也是目前市面上流行的一种手机通讯录查找功能设计方案,它以高效率和低出错率被广泛采用。姓名查找是进入电话列表前的第一个功能,在进入查找之前,先会判断下通讯录存储是否全空或者通讯录是否完成初始化工作。通过左软键注册的回调函数mmi_phb_highlight_nokia_search_name可以进入查找列表菜单。进入列表的入口函数mmi_phb_entry_search_name中又调用类屏幕函数ShowCategory5Screen_nokia,将pbName作为接收用户输入姓名的inboxbuffer。函数mmi_phb_search_name_binary_search就是采用折半查找的思想具体实现了姓名查找的功能。因为姓名查找表属于有序表,g_phb_name_index[]中就是按照字母顺序保存,提取PhoneBook中的姓名可以和输入的姓名进行比较。它的待查记录所在的区间就是(0,(PhoneBookEntryCount-1))。需要注意的是,中文字符采用的是USC2编码方式,每个中文字符用16位的Unicode字符表示。如果是中英文混合,英文字符只占1字节,需要补零成为16位的编码。所以按位拷贝的时候要注意申请空间。在每一次的查找中,都要将mid所对应entry的姓名和查询输入的pbName值之间的比较,每次的比较都得到两个返回值:一个是统计相同字符个数的same_count,一个是记录第一位不同字符的比较值distance。通过distance再确定后一个mid值。查找结束后根据mid值马上就能确定index:result_index=mmi_phb_search_name_binary_search(0,(PhoneBookEntryCount-1),(S8*)pbName);既然查找到对应的entry,就将该条目高亮:g_phb_cntx.highlight_entry=mmi_phb_search_name_find_closet(); 55第四章通讯录应用的设计与实现4.4.5复制或转存复制就是保留本身的存储不变,在另一个存储区中添加一条基本信息完全一样的条目。转存是指在另一个存储区完成添加后,再删除本身存储的所有信息。其实从功能上看,前者就是先读取再添加,后者还需要最后删除,这就要用到前面讲的添加和删除对应的消息传递方式。多条操作就是单条操作的重复,单条复制和转存的消息就是添加和删除的消息:PRT_PHB_SET_ENTRY_REQPRT_PHB_SET_ENTRY_RSPPRT_PHB_DEL_ENTRY_REQPRT_PHB_DEL_ENTRY_RSP从界面上看,复制后需要返回到电话列表中,实现方法:调用函数mmi_phb_entry_list后,并将g_phb_cntx.highlight_entry设置成复制好的新电话条目。转存后返回的并不是全部的电话条目列表,仅是显示和高亮转存成功的那一项。窗口的管理和相应函数前面都已经详细介绍过,这里就不再赘述了。4.4.6相关设置功能通讯录的设置功能有很多,例如可以对语音信箱号码、存储方式选择、存储状态显示、列表查看方式、头像显示关闭或开启进行设置。语音信箱号码设置属于应用交互部分,因为这是由短信息应用完成的,通讯录这里只是准备了调用其他应用的接口函数。存储方式选择其实就是修改g_phb_cntx.prefer_storage的值,当刚进入这个菜单项后,根据g_phb_cntx.prefer_storage的值选择高亮项:if(g_phb_cntx.prefer_storage==MMI_SIM){hiliteStorage=0;}else{hiliteStorage=1;} 55第四章通讯录应用的设计与实现用户可以通过键盘上下操作选择存储方式,每个菜单项都设置好了对应的高亮处理函数和g_phb_temp_storage值。当左软键确定好存储方式,就调用函数:mmi_phb_storage_location_set_req。它除了给L4发送设置存储方式的消息:PRT_PHB_SET_PREFERRED_STORAGE_REQ外,还需要将修改过的变量g_phb_temp_storage值写入NVRAM,同时也要修改g_phb_cntx.prefer_storage值:g_phb_cntx.prefer_storage=g_phb_temp_storage;tempStorageLocation=g_phb_cntx.prefer_storage;WriteValue(NVRAM_PHB_STORAGE_LOCATION,&g_phb_temp_storage,DS_SHORT,&pError);存储状态显示是读取出存储区的容量值,分别列出SIM卡和NVRAM中的已占用和未占用的容量值。高仿的某款手机NVRAM最多可以存取200条,SIM卡最多可以存取150条。读取容量值的操作不需要和L4发送消息,可以直接通过g_phb_cntx.phone_total、g_phb_cntx.phone_used、g_phb_cntx.sim_total和g_phb_cntx.sim_used的值计算出来。列表的查看方式就是可以选择电话列表显示风格,有三种:只显示姓名(无姓名的就只显示号码),或者只显示姓名和号码,或者显示姓名、号码、头像。通过这三种方式设置全局flag,当进入电话列表时,类屏幕函数会根据flag的值选择显示电话条目的内容,基本的显示方法前面已经介绍了。头像的显示开启或关闭也采取以上的设计思路,通过全局变量标识来控制列表或条目的显示内容。4.5应用间的交互应用并不是独立作用的,它可以和其他应用交互。通讯录应用可以和短信息、通话管理、通话记录等应用直接或间接产生联系,这就需要合理的去设计相关的交互接口,以保证整个系统的稳定性和易操作性。前面介绍过,其他应用调用通讯录应用的功能和可操作权限是不太一样的,以此为出发点我们通常把通讯录相关的交互接口的定义和声明写在文件:PhoneBookGProt.h和PhoneBookStubsToOthers.c中。在与通讯录交互中最典型的就是调用电话列表,比如发送短信息需要查找列表选择联系人,建立黑名单或者聊天室也是需要查找电话列表等等。枚举变量MMI_PHB_LIST_VIEW里面就列举了很多其他应用调用的情况:typedefenum{......MMI_PHB_LIST_FOR_SMS,//发送短信息MMI_PHB_LIST_FOR_CHAT,//建立聊天室MMI_PHB_LIST_FOR_SETTINGS,//建立呼叫转移MMI_PHB_LIST_FOR_CM,//通话管理MMI_PHB_LIST_FOR_MMS_NUMBER,//彩信号码 55第四章通讯录应用的设计与实现MMI_PHB_LIST_FOR_MMS_EMAIL,//彩信邮件......MMI_PHB_LIST_FOR_EMAIL_APP//邮件}MMI_PHB_LIST_VIEW;下面就以具体功能的设计与实现来说明如何实现应用间交互的:对于每一个电话条目都可以把自己的号码直接作为短信编辑内容准备发送,这样调用短信息应用的方式就是前面介绍的直接调用。根据当前的index读出对应的电话号码,将其作为短信文本内容,再调用短信息应用的发送短信的入口函数mmi_msg_send_msg_to_only_entry。如果flag_for_send_phoneNo值为1,表示是通讯录应用在调用短信息应用来发送本号码,这时就调用mmi_msg_send_msg_req准备开始给L4发送消息,后面的部分就完全属于短信息应用了。在短信息应用中查看通讯录列表,属于间接显式调用通讯录应用。在编辑好短信息之后,可以进入电话列表选择电话号码。短信息应用中的函数mmi_msg_send_msg_to_only_name_entry就开始调用通讯录应用中的mmi_phb_search_name_pre_entry。由于变量phbListView这一次被赋值为MMI_PHB_LIST_FOR_SMS,所以开始进入列表前是通过函数:mmi_phb_list_pre_entry_second_level,并不是调用通讯录应用自身显示列表调用的mmi_phb_list_pre_entry。然后再调用了mmi_phb_entry_list显示电话列表。还有一个不同的是,这次注册的高亮回调函数是mmi_phb_get_index_second_level,它会将选中的电话号码赋值给g_frm_sms_cntx.mmi_frm_sms_number,完成以后就再回到短信息模块准备发送给L4发送消息。通话模块与通讯录应用的交互设计有两方面:一是通话管理模块中隐式调用通讯录,即来电匹配问题。当有电话呼入时,首先得到号码,依次在NVRAM和SIM卡的记录中匹配查找,如果存在相同的号码,则认为匹配成功,将姓名复制到通话信息结构体CALL_INFO的结构成员name中,然后显示在呼叫界面上。另一方面考虑的则是在通讯录应用中调用呼叫功能。这个与通话管理模块进行交互的过程,其实现方法与直接调用短消息应用是类似的。4.6高级功能快速查找通讯录的快速查找功能是前面姓名查找的功能优化,可以说是一种高级查找方法,它是通过姓名的拼音字母依次查找的。比如用户在电话列表中想快速查找到一个叫张小明的联系人,对应姓名的字母为“zhangxiaoming”。当先输入字母“z”后,列表将显示以“z”为首字母开头的所有联系人。继续输入字母“h”后,列表将显示以“zh” 55第四章通讯录应用的设计与实现为首字母开头的所有联系人。当用户找到匹配的姓名时,可能已经输入了三个以上的字母了,而每次的输入都会使当前的电话列表重新显示一次。根据上面的功能分析,我们知道当用户输入一个字母后,输入的字母需要和所有的entries的前两个字节比较,把符合的entry逐一加到一个指针数组中。用户输入第二个字母后,再把输入的所有字母与所有的entries比较,再次设置指针。所以可以把快速查找的每一个查找过程都看作成前面提到的姓名查找。按照这个思路,我们就可以基于姓名查找功能来实现快速查找功能了。下面是函数调用的过程:函数mmi_phb_quick_search_make_cache把PhoneBook[]中的entries姓名第一个字母(前2个字节),放入g_phb_qsearch_cache[]中。其中,又是通过函数mmi_phb_quick_search_convert_cache来对通讯录的每个条目进行汉字到拼音的转换,如:“张”对应“zhang”,并存储到g_phb_qsearch_cache[]的相应位置,这样便完成了汉字到拼音的映射。当用户输入字母“z”时,函数gui_single_line_input_box_insert_multitap_character会把“z”插入记录编辑框内容的数组MMI_singleline_inputbox中,然后调用cat200_search_function,它把输入的字母与PhoneBook[]中比较、过滤,设置g_phb_qsearch[]。操作输入框的回调函数Cat200multitap_inputcallback根据g_phb_qsearch[]的值,动态获取匹配的entry,然后再调用函数refresh_search_list_change_list,更新显示动态电话列表。需要说明的是,当第一次显示列表的时候,设置g_phb_qsearch[]全部为1。屏幕最下面在输入的时候会有multitap显示用户输入的内容。用户输入第一个字母后,把这个字母与所有entries的首字母比较。若相等,设置g_phb_qsearch[i]=1,否则g_phb_qsearch[i]=0。然后重新获取所有g_phb_qsearch[i]值为1的entries,并显示符合查找内容的动态列表。用户输入第二个字母后,把这两个输入的字母与所有的entries比较,再设置g_phb_qsearch[i],根据非零值重新显示列表。不管是继续输入还是删除输入时,所做的操作都和前面是一样的。高级查找的最大缺点是查找速度比较慢,由于整个算法需要不停的通过按键和按键次数来确定输入的是哪个字母,将大量运算时间花费在寻找其在拼音序号影射表的位置上,因而时间复杂度较高。基于项目时间的限制和系统稳定性的考虑,高级查找界面中的部分控件的显示风格会和客户要求的某款高仿机有少许差异。由于这部分涉及UI中部分控件的重新部署,还在进一步的测试和修改中,直至其完善成熟起来,预计在后续项目中将会被逐渐应用。4.7小结 55第四章通讯录应用的设计与实现通讯录应用作为手机平台上层应用的典型代表,是最重要功能之一。本章通过详细的需求分析,从界面显示、重要功能实现、应用间的交互几个角度对通讯录应用做出了详细的软件设计。通过解决开发中遇到的种种问题,如初始化工作的设计、屏幕流管理、窗体绘制和图层编写等,不仅实现了通讯录应用的基本功能和界面,并对通讯录快速查找问题作了深入的尝试和研究,提出了个人的一些解决思路和修改建议。 69第五章手机应用层的软件测试第五章手机应用层的软件测试5.1手机应用层软件测试方法[35]移动电话已经发展成为综合了语音和数据功能的复杂移动设备,因此要求在开发过程中执行广泛的高效的测试,实现快速上市的目标,以便在全球市场的竞争中立于不败之地。在无线设备开发中的测试可以分成以下七种类型:1.基本功能测试:收发IP数据,用户常用功能和有限的检查2.规格测试:根据规格要求进行测试和测量3.回归测试:对修改版进行基本功能和规格验证4.全操作范围功能性测试:在各种网络条件下进行全面的功能性检查5.意外情形下的功能性测试:非法参数值和特殊事件序列6.互通性测试(IOT):验证多种网络下的互通性7.一致性测试:验证与颁布标准的一致性图5.1列出的测试类型1、2和3是最常做的几类测试,在每个新版软件或硬件的开发过程中这些测试几乎是连续完成的。类型4和5的测试在开发过程中是偶尔做一下的,通常针对变化较大的改版,在整个生命周期内只做几次。类型6和7的测试很少做,一般安排在产品开发的最后阶段,在整个开发过程中只做1到2次。回归测试规格验证基本功能测试互通性一致性不期望出现的情况全工作范围应用软件技术元件平台参考设计最终产品结构制造图5.1手机开发测试类型 69第五章手机应用层的软件测试上面介绍的手机测试是一个很广泛的概念,涉及到硬件测试、软件测试,还有结构的测试。而手机软件测试多指的应用层软件测试,这是由于现在市场上很多不同型号的手机具有相同的硬件平台和操作系统,它们在功能和性能上的差异更多地体现在应用层软件上。因此,从应用层软件的层面加强测试,能更为有效地发现手机的质量问题。手机软件系统测试可分为:功能模块测试,交叉事件测试,压力测试,容量性能测试,性能测试和用户手册测试等。1.功能模块测试:首先应分析功能模块的功能项,测试每个功能项是否能够实现对应的功能。一般根据测试案例(TestCase)或软件本身的流程就可以完成基本功能测试,相对方法简单,故障也较容易解决2.交叉事件测试:又叫事件或冲突测试,是指一个功能正在执行过程中,同时另外一个事件或操作对该过程进行干扰的测试。例如通话过程中接收到短信或者响铃闹,应该确保这类的冲突事件不会导致手机死机或花屏等严重的问题。交叉事件测试非常重要,能发现很多应用中潜在的性能问题。另外有中英文模式的切换的手机要注意中英文模式切换后的功能实现存在的问题,通常会被测试人员忽略。3.压力测试:又叫边界值容错测试或极限负载测试,即测试过程中,已经达到某一软件功能的最大容量,边界值或最大的承载极限,仍然对其进行相关操作。例如连续进行短信的接收和发送,超过收件箱和SIM/PIM卡所能存储的最大的条数,仍然进行短消息的接收或发送,以检测软件在超常态条件下的表现,来评估用户能否接受。压力测试用手工测试非常繁锁,可以考虑自动化测试,目前没有比较大量使用的工具,一般都是由开发人员配合开发出的工具,或者高级的测试人员编写出的脚本。4.容量测试:又叫满记忆体测试,包括手机的用户可用内存和SIM/PIM卡的所有空间被完全使用的测试。此时再对可编辑的模块进行和存储空间有关的任何操作测试,如果软件的极限容量状态下处理不好,有可能导致死机或严重的花屏等问题的出现。与压力测试有些类似,也可考虑自动化测试5.兼容性测试:也就是不同品牌手机,不同网络,不同品牌和不同容量大小的SIM/PIM卡之间的互相兼容的测试,以短消息为例:中国电信的小灵通接收到从中国移动或中国联通GSM发来的短消息,接收、显示和回复功能是否正常等。从测试是否针对系统的内部结构和具体实现算法的角度来说,软件测试方法分为白盒测试和黑盒测试。黑盒测试是已知产品的功能设计规格,测试证明每个实现了的功能是否符合要求。白盒测试则是已知产品的内部工作过程,可以通过测试证明每种内部操作是否符合设计规格要求,所有内部成分是否以经过检查。 69第五章手机应用层的软件测试手机性能测试的方法按照自动化程度不同可分为手工测试和自动测试。手工测试主要是通过测试人员手动操作,并借助某些监测仪器和工具,来验证手机性能。自动化测试主要是采用自动化测试工具替代人工实现大量手工难以完成的工作,重复性较强的工作,能够完成大量的回归测试,易于维护。5.2MTK平台软件仿真工具[36]手机软件是需要在手机上运行的,它必须下载到手机上。但是在开发手机软件的过程中不可避免的需要对软件进行大量的开发、调试和修改工作。每次改动都要编译,生成下载文件,最后都要下载到手机上。这样无疑降低了效率,也不利于样机的硬件。在PC机上通过手机模拟器来调试软件,检查软件的有没有正确的完成想要的功能也是测试前不可或缺的工作。MTK平台提供的软件仿真工具是MoDIS(MoblieDevelopementIntegratedSystem),它的PC模拟版是使用VC的编译器和链接器生成,ARM版使用ADS1.2的编译器和链接器生成。因为MTK的整个软件系统是一个很庞大而且复杂的工程,并且要支持多个MTK的产品系列和多家客户的客户化支持,使用集成开发环境(IDE)已经无法胜任,而且很难做到整个工程的自动构建和资源、代码的生成。所以MTK的软件系统使用了Windows下的GNU开发工具链(MinGW)来进行工程的管理、配置和构建,MTK将MinGW放到了第三方工具中。另外还使用了perl脚本来解析用户输入的命令行参数,因此第三方工具中还包含了ActivePerl(windows下的perl解释器)。不过,整个软件系统并没有使用MinGW的全部工具,只使用了make这个工具,由几个Makefile控制了构建的过程。可以通过查看工程目录modis找到虚拟的GSM网络、SIM卡等,以及模拟器需要的字符串、图片等资源,还有PC模拟版的库、VC的相关工程文件。此工具运行的硬件要求为:CPU:至少1.5GRAM:大于512MB软件环境为:WindowsXP/Windows2000通常每个平台为软件开发提供一系列的开发套件,常用的有仿真软件、Trace跟踪分析软件、Download目标代码的装载软件等等,通过这些软件实现手机同PC的数据交互,实现软件的开发仿真,问题的跟踪分析,以及程序的灌写等。手机软件MMI的自动化测试需要手机终端和计算机进行通讯,所以通讯方式可以选择串口或者蓝牙,鉴于稳定性和易用性,设计简单程度,串口通讯是非常简单的很容易实现的。图5.2是仿真工具MoDIS的界面,它由模拟器主窗口和调试窗口组成。当MoDIS运行结束之后会在执行文件MoDIS.exe所在路径下生成MoDIS.ini,以便保存系统的设定信息。 69第五章手机应用层的软件测试图5.2MoDIS的界面组成MoDIS仿真工具可以模拟很多功能,如多任务处理、文件系统、驱动(COM口、LCD、SIM、CSR蓝牙、图像解码)、网络性能(socket接口、WAP、MMS、OMAPOC、OMAIMPS、Email)、Catcher工具、附加工具(皮肤模板、层管理)。所有与MoDIS模块相关的文件都在工程目录modis下,图5.3为该模块的工作区:图5.3MoDIS文件和文件夹结构其中有几个重要的文件和文件夹:_BUILD_LOG:存放命令行编译结果drv_sim:存放驱动模拟功能的源代码 69第五章手机应用层的软件测试FileSystem:存放文件系统的源代码MoDIS:存放MoDIS主要功能的源代码MoDIS_lib:存放MoDIS重要的库MoDIS_UI:存放MoDIS皮肤的相关文件WIN32FS:存放为Windows文件系统提供的驱动模拟MoDIS.dsw:MoDIS工作区createMoDIS.pl:生成MoDIS工程的批处理文件createMoDIS.ini:MoDIS全局配置文件开始使用自动化测试工具MoDIS前需要完成下面的步骤:1.基于target设置来创建MoDIS:用new来建立target,到更新资源的时候要确保没有任何错误。new是全新开始构建整个工程的ARM版,包括图片、声音、字符串等资源都要重做,依赖的其他动作最多,是最彻底也是耗时最长的一个动作,一般得到一个新的MTK发布版本后要做一次。2.建立环境设置:调整PC机中的几个设置(路径、库),路径中加入msdev.exe和cl.exe,LIB设置包括VC98LIB和VC98MFCLIB。3.配置MoDIS工作区:在文件createMoDIS.ini中添加或删除设置。4.生成MoDIS工作区:make命令或批处理语言createMoDIS.pl。完成这一步后,每个模块都会生成自己的ini、dsp文件。5.生成MoDIS数据库:make命令或批处理语言modiscodegen.pl。6.编译源代码建立MoDIS:点击MoDIS.dsw,用VisualC++打开MoDIS工程。也是用make命令或批处理命令:Msdev/MAKE"MoDIS-wIN32"[/clean]在开机状态下,内部软件其实一直在不停的处理各层之间的消息,Catcher工具就是用来截获各层之间的消息,以方便查找bug。它有两种运行模式:日志模式和MoDIS日志模式。前者用于真机,后者用于MoDIS。使用Catcher工具捕获MoDIS中消息的步骤:1.开启Catcher,将数据库连接路径设为:tstdatabase_modis2.选择MoDIS日志模式:菜单Control->Mode->MoDIS->MoDISLogging3.开始建立跟踪连接:菜单Control->Connect4.开启或关闭截获要截获的层的消息:菜单Control->SetFilter使用Catcher工具捕获真机中消息的步骤:1.设置手机:输入*#3646633#->Device->SetUART->TSTConfig->UARTPort,设为UART1,完成后关机2.开启Catcher,菜单Config->SetDatabasePath,选择路径: 69第五章手机应用层的软件测试Projecttstdatabase(_classb)下的BPLGUInfoCustomSrc3.选择MoDIS日志模式:菜单Control->Mode->MoDIS->LoggingMode4.按下configureRS2325.开始建立跟踪连接:菜单Control->Connect6.开启或关闭截获要截获的层的消息:菜单Control->SetFilter图5.4Catcher工具5.3通讯录应用的测试用例由于第四章以通讯录应用为例详细讲述了应用层软件设计及实现,且本人后期也从事了此模块的测试工作。因此,下面仍以通讯录应用为例来阐述手机应用层软件的测试要求。1.基本功能说明:通讯录中的电话条目的添加、删除、编辑、查找、设置、快速拨号、来电免打扰等相应的功能和界面实现正常。其中还包括部分功能的批量操作(SIM卡记录复制到手机、手机记录复制到SIM卡、SIM卡记录移动到手机、手机记录移动到SIM卡等等)。2.完成通过测试和失败测试:通常的失败测试,也就是说要设计测试用例,迫使软件出错。通过测试则是要保证软件实现基本功能。 69第五章手机应用层的软件测试3.完成集成测试,检查通讯录应用与其它应用交互是否正常。例如呼叫、MMS、短消息等等。5.3.1基本功能测试手机输入法有很多种,比如T9、拼音、字母、数字等等。在编写测试用例的时候,首先要保证各输入法是否能正常输入;能否正常保存;在进行错误输入的时候,是否有响应的提示。另外,存储在手机上的记录和存储在SIM卡上的记录的测试用例基本相同。在测试过程中需要留心的是SIM卡的存储容量以及手机的存储容量,由于软件的定制不同,往往在不同处易出现故障。比如SIM卡的姓名栏可存储5个汉字,或8个字母、数字,电话号码可以存20位,手机的姓名栏目可以存12个汉字,20个字母、数字,电话号码可以存30位。在这个不同点之间就容易出现故障。下面以个别功能为例说明测试方式:A.添加1)姓名输入i)是否可以使用任意输入法添加汉字、字母、数字,达到姓名允许的最大字节,并能正常保存。ii)是否可以使用任意输入法添加汉字、字母、数字,在没有进行输入时,是否有警告提示或是否可以正常保存(根据产品要求)。iii)是否可以使用任意输入法添加汉字、字母、数字,超过姓名允许的最大字节,是否有警告提示或是否可以正常保存。iv)是否可以进行汉字、字母、数字的混合输入,并重复i~iii,是否有异常。2)电话号码的输入i)是否可输入数字至最大值,并可正常保存。ii)在不输入数字时,进行保存时,是否有告警提示。iii)是否可以输入汉字、字母,此时是否有告警提示或异常。iv)是否可以输入特殊字符,如+、p、*、#,是否可以正常保存。3)在输入过程中按返回键、挂机键、或翻合翻盖、电源键,是否有告警提示或异常。4)在各MMI界面下,各按键功能是否正常。5)待机界面下直接输入数字至最大值,是否可以正常保存。6)待机界面下直接输入数字即特殊字符(+、p等),是否可以正常保存。7)将1至6步骤进行一下排列组合,查看是否有异常情况。B.删除1)对单条记录进行删除i)删除后,列表显示是否正常,数量是否正确。 69第五章手机应用层的软件测试ii)记录为空时,进行删除时,是否有告警提示。iii)记录仅为一条时,删除后,是否有内容为空的提示。iv)在删除过程中,各功能键是否正常。v)在删除过程中,进行中断操作,是否正常,比如挂机键,电源键等等。2)对多条记录进行删除,目的是对软件的进行压力测试。i)连续对多条记录进行删除,是否出现异常情况。ii)删除记录直至为空时,是否有异常。iii)在删除过程中,各功能键是否正常。C.编辑1)单条记录的编辑i)是否可以对单条记录进行编辑,包括姓名和数字,并重复测试添加功能中的1至4各步骤。ii)连续将多条记录的内容(姓名或电话号码)修改成一样。iii)手机或SIM卡的所有记录全部一样(此条仅作为一条测试手段,在实际的应用中无实际意义)。2)连续多条记录进行编辑(此条的测试目的是对软件进行压力测试)。5.3.2批量测试A.SIM卡记录复制到手机1)1条SIM卡的记录复制到手机i)姓名为1个字母或数字或一个字,手机号码是1个数字或特殊字符(+、p等)。ii)姓名为满的字母或数字或字符,手机号码是满的数字或特殊字符(+、p等)。2)将SIM卡的记录全部复制到手机前提条件:SIM卡的容量有限,有的是70(如动感地带,易通卡),有的是大容量卡有200甚至250条的记录容量(如全球通,各地区的SIM卡容量不同,在测试过程中要考虑到对卡的兼容性),保证手机的每条记录是满记录,即姓名栏的字母,数字或汉字为满,号码栏的数字为满。将记录全部复制到手机,查看是否有异常。通常这时候问题就出来了,因为是批量性的复制,和手机的处理能力是有一定关系,此处比较容易出问题。3)手机记录的容量通常比SIM卡的容量要大许多,这里在谈一下该处的测试要点。前题条件:SIM卡的每条记录全满,即姓名和电话的容量全满。i)SIM卡记录全部复制到手机,直至手机记录满,是否有相关的提示,例如:手机记录满,手机空间不足,是否继续进行复制、部分记录将会丢失的字样。 69第五章手机应用层的软件测试ii)手机是否可以读取大容量的SIM卡,包括全部的手机记录,并能进行正常的查找。此处,可以连续的单条删除手机或SIM卡记录,直至删空,查看是否有异常。B.手机记录复制到SIM卡说明:手机的记录由于设计不同,有的手机是一个姓名对应一条记录,有的是一个姓名对应多条记录,具体根据实际情况。1)将一条手机记录复制到SIM卡上,是否正确复制。注意:手机记录中的姓名栏可能和SIM卡姓名栏的字数不相同,这时需要注意异常现象。另有的手机支持的是一个姓名下有若干条手机记录,是否可以将若干条记录全部复制到SIM,且无异常现象。2)将全部满的手机记录,即手机存储的条目数满,姓名栏的字全满,手机号码的字数全满,全部复制到SIM卡,查看是否有异常。注意:SIM卡的空间和手机空间容量在相等,或不相等的情况下,在复制的过程中均有提示,例如:SIM卡空间满、空间不足,如空间不足进行复制时,会有部分数据丢失等告警提示。C.SIM卡记录移动到手机SIM卡记录移动到手机同SIM卡记录复制到手机的测试方法基本相同。注意的是在移动后,SIM卡内容清空。D.手机记录移动到SIM卡手机记录移动到SIM卡同SIM卡记录移动到手机的测试方法基本相同。由于各手机设计不同,有一个姓名对应一条记录和一个姓名对应若干条记录的情况,注意在移动过程中出现异常现象。从上面的测试方法已包含了等价测试和边界测试。下面将对测试过程中加入的其它环节进行描述。1)中断:短信,EMS,来电,闹钟,功能键,挂机键等等。在进行上述操作时,在每一个界面下,均需进行中断操作,并根据软件需求说明,对异常情况进行定位。2)在进行每项操作时,均应有提示,确认是否进行该操作。由于各手机软件需求不同,在测试过程中可根据实际情况或根据用户反馈情况进行。3)在SIM卡记录或手机记录满的情况下,添加记录,查看是否有相关提示或异常。5.3.3失败测试根据手机通讯录的实际情况,通过某些方式或方法迫使软件出错。在测试案例的设计中仍按重复测试,压迫测试以及重负测试这三种测试理念进行测试。 69第五章手机应用层的软件测试A.重复测试1)添加i)在待机状态下连续添加电话号码,并保存至SIM卡/手机,操作次数大于40次。ii)添加菜单内连续添加电话号码,并保存至SIM卡/手机,操作次数大于40次。2)删除i)电话列表下,连续逐条删除电话号码。ii)在保证SIM卡/手机容量满的情况下,连续删除SIM卡/手机全部记录,在进行手机全部内容复制到SIM卡上的操作。操作次数大于20次。3)查找根据手机的实际功能,进行连续性查找。查找次数大于20次。4)修改i)连续逐条将记录修改成同一内容的记录,操作次数大于5。ii)连续逐条修改记录,将姓名栏内的内容修改至最大,并将电话号码号码修改至最大。操作次数大于20次。说明:在这里涉及到操作次数的问题,操作次数过大或过小,都会失去它的实际意义。操作次数定义在40次,是根据SIM卡的容量定义的,通常SIM卡的容量是在70左右。连续删除SIM卡/手机的全部记录的20次操作,测试目的是检验内存是否溢出或不足。这项操作也可以定义成50次,甚至更多。即使检测出软件存在问题,但是进行软件更改的成本就会更高,甚至造成代码引入的BUG,总体来讲,得不偿失。B.压迫测试压迫测试是指软件在不够理想的条件下运行——内存小,磁盘空间少,CPU速度慢等等。从经验来看,压迫测试和重复测试相结合,测试的效果比较好。在通讯录中主要是要注意SIM卡容量和手机容量的关系。有部分SIM卡的容量比较大,在200,250条甚至更高。在测试过程中,主要注意的一个问题就是尽量在SIM卡和手机容量慢的情况下进行添加,删除,修改,查找等操作。另一点就是操作的次数不能太少,也尽量不要太大。C.重负测试比如:插上充电器;在低电压时,插上充电器;电池容量满后,继续充电并测试等等。D.其它1)在电话列表下,连续按方向键,进行读取列表;2)在电话列表下,快速插拔充电器;3)输入非正常字符进行存储。 69第五章手机应用层的软件测试……上述用例的目的就是模仿用户在使用过程中或非正常情况下易出现的问题。5.3.4集成测试在这里针对通讯录的测试,采用的是增值式集成测试。通过通讯录与其它模块的相关关系,检测测试通讯录与相关模块在接口上是否存在BUG。在测试过程中,首先测试是否满足基本功能,其实是多次反复调用相关模块,检验模块接口是否有问题存在。5.4通讯录应用的测试结果根据上一节的测试用例,基本功能测试结果如下:表5.1基本功能测试结果序号测试功能功能描述期望结果测试结果P/FPB_01读取1.进入通讯录电话列表,显示界面;2.记录为空时,弹出详情界面1.电话列表显示正常;2.记录为空时,弹出提示框显示正确符合期望结果PPB_02查找1.按输入的姓名首字母进行查找;2.用户输入内容和输入法可以修改1.进入电话列表,查找正确;2.高亮查到的最符合项符合期望结果PPB_03快速查找1.按输入的姓名首字母进行查找,显示输入框;2.用户输入内容和输入法可以修改1.输入框正确显示,查找正确;2.高亮查到的最符合项符合期望结果PPB_04添加到手机1.进入编辑电话条目界面;2.进入存储界面按左软键确认添加,返回查看存储类型正确,列表显示含该项符合期望结果PPB_05添加到SIM卡1.进入编辑电话条目界面;2.进入存储界面按左软键确认添加,返回查看存储类型正确,列表显示含该项符合期望结果PPB_06单条删除1.符合期望P 69第五章手机应用层的软件测试选择要删除的条目(SIM卡/手机);2.操作提示界面按左软键确认删除,返回电话列表查看此记录不再存在结果PB_07多条删除1.选择全部删除或逐条删除;2.操作提示界面按左软键弹出提示框确认,返回电话列表记录为空或记录不再存在符合期望结果PPB_08编辑1.选择要编辑的条目(SIM卡/手机);2.进入编辑电话条目界面;3.进入存储界面按左软键确认保存,返回查看存储类型正确,查看该项内容已修改符合期望结果PPB_09单条复制/转存1.选择要复制或转存的条目(SIM卡/手机);2.操作提示界面正确复制或转存该条目,电话列表有对应显示符合期望结果PPB_10多条复制/转存1.选择复制或转存的方式(从SIM卡到手机或从手机到SIM卡);2.选择全部操作或逐条操作;3.操作提示界面能够复制或转存该条目,电话列表有对应显示符合期望结果PPB_11设置涉及设置内容较多,需另外列出略略略PB_12快速拨号1.从电话列表选择号码和2-9绑定;2.主菜单下分别长按2-9快速拨号能够保存绑定内容,快速拨号正常符合期望结果PPB_13来电免打扰1.从电话列表选择号码设置为黑名单项;2.本机为被叫,主叫为黑名单项,呼叫被屏蔽;3.操作提示界面能够保存黑名单设置,所有相关项均呼叫失败符合期望结果P再列举出部分的交叉事件测试结果:表5.2部分交叉事件测试结果序号测试功能功能描述期望结果测试结果P/F 69第五章手机应用层的软件测试PB_14来电1.进入通讯录进行编辑/查找等基本操作时;2.突然来电话正常接听电话,接听完毕返回通讯录刚才的操作界面符合期望结果PPB_15来短信1.进入通讯录进行编辑/查找等基本操作时;2.突然来短信正常查看短信,完毕返回通讯录刚才的操作界面符合期望结果PPB_16闹钟响1.进入通讯录进行编辑/查找等基本操作时;2.闹钟定时到可以正常关毕闹钟返回通讯录刚才的操作界面符合期望结果PPB_17进入短信模块进入通讯录列表选择手机/SIM卡的记录短信中正确显示所选联系人的号码符合期望结果PPB_18短信进入通讯录短信中选择发送号码进入通讯录电话列表界面向选择的记录正确发送信息符合期望结果PPB_19通话历史调用通讯录1通话历史中存储电话操作信息;2.该记录呼叫本机未接/已接/已拨/拒接列表中正确显示该记录信息符合期望结果PPB_20通话管理调用通讯录1.通话过程;2.查阅通讯录电话列表通讯录电话列表信息正常显示符合期望结果P 71第六章总结与展望第六章总结与展望A302项目经过了长达半年的开发及调试期,最终按期完成并交付投产。通过系统部所有从事该项目的同事的协助下,各应用层模块均按照用户需求分析书的要求,成功实现了各自独立部分和交互部分的功能及界面。在该项目中,本人负责的是通讯录应用的上层MMI设计编写。在开发阶段,按时完成了界面显示和功能实现、模块间的交互的全部任务,并使用MTK平台提供的仿真工具进行了详细的跟踪和初步检测;在测试阶段,认真编写了该应用的黑盒测试用例,并最终完成相关的全部测试。该项目的样机通过用户试用审核后,其操作方便、系统稳定达到商用标准,成品顺利流入市场。虽然基于MTK平台高仿某款手机的项目已经完全结束,可是在开发过程中大家也遇到了很多问题,当然难免也会犯错,不过及时的讨论开会将项目开发又引向正轨。在以后的工作中,我们会借鉴这次的不足,从中吸取教训来减免更多的失误。根据这次的项目经验,本人总结了一些不足,确定了下一步的发展方向:1.程序框架可以改进,使代码编写更灵活。2.编程水平需要不断提高,以使代码有更高的可读性和可调试性。3.由于客观因素制约,通讯录应用与其他应用交互完成的快速拨号功能中的部分功能(快速拨号短信)未能添加到真机中,可以考虑在后续同类型项目中引进,加强测试和修正,使之真正应用于实践中。4.手机测试知识薄弱,经验不足,实践使用不够,应该加强测试方面的学习和研究。近年来,手机也向智能化方向发展。本项目高仿的某款手机是早期的SymbianS40系统,不属于智能手机系统。智能手机除了具备普通手机的通话功能外,还具备了PDA的大部分功能,特别是个人信息管理以及基于无线数据通信的浏览器,GPS和电子邮件功能。它为用户提供了足够的屏幕尺寸和带宽,既方便随身携带,又为软件运行和内容服务提供了广阔的舞台,很多增值业务可以就此展开,如:股票、新闻、天气、交通、商品、应用程序下载、音乐图片下载等等。结合3G通信网络的的支持,智能手机的发展趋势,势必将成为一个功能强大,集通话、短信、网络接入、影视娱乐为一体的综合性个人手持终端设备。 71第六章总结与展望 73致谢致谢本论文是我在硕士研究生实习期间的工作总结,在此谨向关心和帮助过我的老师、实验室同学、软件学院同学表达我最诚挚的敬意。首先,向我的学校导师李鹏教授表示衷心的感谢。从论文的选题,课题研究,以及理论深度把握,直到论文的撰写,每一步都凝聚了李老师精心的指导和热情的帮助。李老师严谨的治学态度、一流的学术水平和严肃认真的做事风格都是我今后工作和学习最宝贵的财富。在此,对李老师给我的帮助表示衷心的感谢!其次,向我的企业导师杨睿琦高工致以崇高的敬意。从论题的具体实现及其现实意义,再到项目的开展及其开发方向的把握,杨老师都给予我充分的指导和示范。杨老师传授我工程经验,提供开发资源,保证了整个毕业设计的顺利完成。感谢学院和系上的各位老师和领导,感谢他们传授我知识,在学习上和生活上给予了我许多帮助和指导;感谢实习单位的各位领导,感谢他们给予我足够的信任和帮助,并鼓励我从事前沿性研究和创新工作,感谢他们在项目开展过程中给予我的支持和帮助!感谢师兄李光、冯军、李鹍及同班同学王敏、朱雷、葛宗、田影影等,是他们在生活、学习、工作、研究各个方面都给了我无限的支持和帮助!衷心感谢我的家人,是他们给了我无私的关怀和默默的支持,使我能够全身心的投入学习和工作中来!'