一种启动方式敏感的Android应用返回栈状态静态模拟方法与流程

文档序号:17396658发布日期:2019-04-13 00:52阅读:260来源:国知局
一种启动方式敏感的Android应用返回栈状态静态模拟方法与流程

本发明属于android移动应用软件静态分析技术领域,具体涉及一种启动方式敏感的返回栈静态模拟方法。



背景技术:

android已经成为移动设备上最流行的操作系统。android应用的种类丰富,数量庞大,在人们生活的各个方面均得到广泛应用。activity是android应用程序最重要的组件之一,负责向用户提供交互界面。android系统把软件运行过程产生的activity实例以栈的形式组织在返回栈中,以便用户正确返回到前一层界面(前一层activity实例)。返回栈顶层activity实例为当前界面,与其进行交互能够触发activity间的跳转,改变返回栈状态。activity间的跳转关系构成了一个android应用的整体框架,对其建模能够支持多种上层研究和应用,比如:gui模型构建、gui测试、漏洞挖掘、缺陷检测等。activity跳转由activity启动和返回动作触发,并且返回动作的目标activity需要依靠当前返回栈状态来决定。因此,准确模拟返回栈状态变化对于构建activity跳转模型至关重要。

android应用开发工程师能够通过配置与返回栈状态相关的属性来控制activity启动引起的返回栈状态变化。对于activity启动而言,默认配置要求系统创建一个新的activity实例并将其压入返回栈。特殊配置则会对返回栈产生特定效果,比如:若一个启动关系中目标activity的“launchmode”属性设置为“singletask”,且其“taskaffinity”属性值与应用包名相同,那么在启动目标activity时,系统会首先查找返回栈中是否已经存在目标activity的实例,若存在,则将返回栈中该实例以上的activity实例全部销毁,否则创建一个目标activity的新实例并压入返回栈。

当前activity跳转静态分析没有对影响返回栈状态的相关属性进行提取,并假设所有activity均以默认配置被启动。显然,对于使用了特殊配置的android应用,当前方法无法正确模拟其返回栈的状态变化,从而错误的定位返回动作的目标activity,产生非法activity跳转。包含非法activity跳转的非法路径严重影响基于activity跳转分析的上层应用,比如:在基于模型的gui测试中,测试用例以动作路径的形式被动态执行,而执行非法路径时则会由于错误执行非法动作导致测试失败,影响测试效率和准确性。

android系统中的组件间通信使用intent对象来传递信息,从而启动目标组件。为了确定目标activity并提取与返回栈状态相关的属性配置,需要通过指向分析来解析intent对象的字段内容。与典型java程序只有一个入口不同,android应用程序包含大量回调函数,用户和系统动作都会触发相应回调,即android应用程序包含多个入口。因此,如何有效处理android程序的事件驱动复杂控制流是指向分析需要克服的挑战。



技术实现要素:

本发明目的是解决当前activity跳转分析对启动方式不敏导致返回栈状态模拟不正确的问题,提供一种启动方式敏感的android应用返回栈状态静态模拟方法。

本发明技术方案

一种启动方式敏感的android应用返回栈状态静态模拟方法,包括如下步骤:

第1、所述方法涉及的基本概念:

1)定义1、activity启动方式;

2)activity启动图(activitylaunchinggraph,简称alg);

3)返回栈状态变迁图(backstacktransitiongraph,简称bstg);

第2、启动方式敏感的android应用返回栈状态静态模拟方法的具体步骤:

步骤1、android应用预处理;

步骤2、通过启动方式敏感的activity跳转分析生成activity启动图;

步骤3、基于activity启动图生成返回栈状态变迁图。

本发明方法的具体实现过程如下:

第1、本发明方法涉及的基本概念;

1.activity启动方式定义;

android系统启动activity时,影响返回栈状态的相关属性配置,被定义为activity启动方式;影响启动方式的android相关属性被定义为返回栈状态相关属性。

所述方法总结了4个返回栈状态相关属性以及7个启动方式;4个返回栈状态相关属性分别是:启动关系中目标activity的“launchmode”和“taskaffinity”,启动activity时activity间通信的api调用所传递的intent对象的标志,是否有apifinish()的调用。一个activity启动关系中,对这四个属性的配置决定了其启动方式。

所述的7种启动方式分别是standard、singletop、standard-cleartop、singletop-cleartop、reordertofront、singletask和standard|finish。有效启动方式及其对返回栈的影响,如表1,其中activity类cn以启动方式lt启动cx被记为设当前返回栈状态为<ac1,ac2,…,acx-1,acx,acx+1,…,acn>,其中acx表示activity类cx的一个实例,ac1为栈底实例,acn为栈顶实例;a’cx是区别于acx的cx的新实例。

表1以不同启动方式启动activity带来的返回栈变化。

2.activity启动图(activitylaunchinggraph,简称alg)定义;

activity启动图为四元组:alg=(lt,n,e,s)。lt是启动方式的集合;n是节点集合,即activity类的集合;e是有向边集合,e={<ns,nt,lt>|ns∈n,nt∈n,lt∈lt},其中ns是边的始点,nt是边的终点,lt是启动方式集合lt中的元素,表示源activity类ns以lt的方式启动目标activity类nt;s为alg的起始节点,为android应用的mainactivity。

3.返回栈状态变迁图(backstacktransitiongraph,bstg)定义;

返回栈状态变迁图为四元组:bstg=(lt,bs,st,bsinit)。bs是返回栈状态集合:bs={<c1,c2,…,ci,…,cn>|ci∈n},其中c1为返回栈的栈底activity实例的类型,cn为返回栈的栈顶实例的类型。st是有向边的集合,表示返回栈状态变迁:st=l∪f,其中l为activity启动所触发的返回栈状态变迁集合,f为返回动作所触发的返回栈状态变迁集合。l={<bss,bst,lt>|bss∈bs,bst∈bs,lt∈lt},其中bss为源返回栈状态,bst为目标activity状态。bsinit为起始节点,该节点表示的返回栈状态只包含一个mainactivity的实例。

第2、启动方式敏感的android应用返回栈状态静态模拟方法的具体步骤如下:

4.步骤1、对android应用预处理;

android应用预处理包含两部分:第一部分为androidmanifest.xml文件解析,从文件中提取的重点信息包括:1)android应用包名;2)注册的activity类名集合act;3)各activity类的intent过滤器;4)各activity类的“taskaffinity”和“launchmode”属性值;第二部分是为指向分析构造辅助main(),以支持后续步骤2所述的启动方式敏感的activity跳转分析。所述辅助main()包含每个activity类的一个对象的堆内存分配语句,及每个activity对象的依据控制流组织的回调函数调用语句。

与传统的java程序只有一个程序入口(main函数)不同,android应用程序为事件驱动,由大量回调函数构成。这些回调函数包括生命周期回调和非生命周期回调。非生命周期回调又包括系统回调和gui回调。为了进行指向分析,需要构建一个辅助主函数将这些回调函数依照控制流组织起来。图1展示了辅助main()的结构。对于activity生命周期回调函数:oncreate()和ondestroy()分别指示activity生命周期的开始和结束;onstart()和onstop()分别在activity可视与不可视时自动调用;onresume()和onpause()则指示了可操作周期,用户可在这段周期内操作activity,比如点击按钮。系统自行触发的系统回调(比如onlocationchanged())和用户行为触发的gui回调(比如onclick())均在可交互周期内被调用。为android应用构建辅助主函数时,只考虑被重写的回调函数。

5.步骤2、通过启动方式敏感的activity跳转分析生成activity启动图;

启动方式敏感的activity跳转分析包含10条面向对象的字段敏感指向分析规则和8条activity启动边生成规则;10条指向分析规则分别针对于:类实例化语句、activity类的实例化语句、复制语句、字段读语句、字段写语句、方法调用语句、设置intent标志语句、显示intent分析、隐式intent分析和activity启动语句;8条activity启动边生成规则分别针对于:无效的返回栈状态相关配置判定、singletask启动边生成、singletop-cleartop启动边生成、standard-cleartop启动边生成、reordertofront启动边生成、singletop启动边生成、standard|finish启动边和standard启动边生成。

5.1符号定义

表2alg构建方法所用的符号定义

表2列出了alg构建方法使用的符号定义。第一部分是java程序的抽象。c表示类和接口的集合,act表示所有activity类的集合。每一个方法体都可表示成语句s。方法体可由对象实例化、赋值、字段读、字段写、方法调用五种原子语句组成。对象实例化意味着堆内存的分配。第二部分定义了指向分析过程中用到的相关方法。pt(r)表示指针r所指向的对象集合。fpt(r,f)给出指针r的字段f所指向的对象集合。第三部分给出确定启动方式所用到的符号。被启动activity类的launchmode,taskaffinity,启动时组件间通信方法传递的intent对象的标志和finish()方法的调用共同影响着返回栈状态,决定了启动方式。launchmode属性的可选值为:“standard”,“singletop”,“singletask”,“singleinstance”。根据intent标志对返回栈的影响将其分为无效标志(ivflag),有效标志(vflag)和其它(oflag)。vflag的可选值为:“flag_activity_clear_top”,“flag_activity_clear_top”,“flag_activity_reorder_to_front”。本发明把引起多个返回栈的交互的intent标志称为无效标志。第四部分给出了alg相关符号。通过指向分析所构造的activity启动图中每个节点都为一个activity类的对象。

5.2面向对象的字段敏感指向分析规则

对辅助主函数进行指向分析,初始时alg的节点集合n和边的集合e都为空。[rule-1]-[rule-6]对应于五条原子语句所对应的指向规则。[rule-1]对应于类实例化语句。[rule-2]专门针对于activity类的实例化。每个activity对象的创建都为alg新增一个节点。[rule-3]-[rule-5]分别对应赋值、字段读、字段写语句。[rule-6]对应了方法的调用语句。每个方法m包含其方法名,形参thism和pm,返回值rm。对方法m进行指向分析可拆解为对m的方法体sm及辅助语句x∶=rm的分析。

android系统通过组件间通信api,比如startactivity(intent)来启动新的activity。intent对象决定了目标activity。intent可以分为两种类型,显式和隐式。显式intent记录了明确的目标activity类型。隐式intent记录了目标activity需要执行的动作,只有具备执行该动作能力的activities才可能被启动。activity能够执行的动作被注册在androidmainfest.xml的intent过滤器中。android平台提供了apis来帮助intent对象记录目标activity相关信息,比如setcomponent(),setaction()。对于显式intent,目标activity类型被存储在字段intent.mcompont.mclass中。对于隐式intent,目标activity需要执行的动作被存储在字段intent.maction中。为intent设置标志字段能够在启动activity达到特殊的效果,比如“flag_activity_clear_top”标志要求系统首先查找返回栈中与目标activity同类型的实例,若存在,则将返回栈中该实例以上的实例全部销毁。

[rule-7]-[rule-10]是组件间通信相关语句指向规则。[rule-7]对intent标志进行分析。intent标志为整数类型。intent对象oi通过调用方法addflags()将标志值存储在mflags字段;也可以通过调用方法setflags(),将添加的新标志与已有标志进行按位或运算并存储在mflags字段。[rule-8]和[rule-9]分别对显式和隐式intent进行分析。为intent对象oi构造了字符串类型的辅助字段targetclassname来存储目标activity类名。[rule-9]中的findtarget()方法返回能够执行oj动作的目标activity集合。[rule-10]分析了所有activity启动相关apis,包括:startactivity()、startactivityforresult()、startactivityifneeded()和menuitem.setintent()。在该项规则中,this表示一个activity实例;启动activity所传递的intent对象oj的字段targetclasssname记录了目标activity类名ok;getactobj()根据类名获取其在堆内存中的唯一实例ol;getflags()将intent对象oj的字段mflags所存储的整数转化为标志集合并返回;getlm()和getta()分别获取目标activity对象的launchmode和taskaffinity;getfin()获取正被分析的方法m的方法体有没有调用finish();表示oi以启动方式相关配置config下启动ol

5.3activity启动边生成规则

[rule-11]-[rule-18]给出了根据activity间启动关系和配置信息生成alg启动边的规则。[rule-11]对应于无效配置的判定,其中pkname是当前android应用的包名。当taf与当前包名不相同时,若系统安装了与taf相同的应用,则会在该应用的返回栈中启动目标activity。无效配置会引起多个返回栈的交互,没有为无效配置的activity启动生成启动边。[rule-12]-[rule-18]分别对应启动方式为singletask,singletop-cleartop,standard-cleartop,reordertofront,singletop,standard|finish,standard的有效边的生成,其中方法configvali()根据[rule-11]来判定配置信息是否有效,若有效,则返回true。

6.步骤3、基于activity启动图生成返回栈状态变迁图;

返回栈状态变迁图构建方法以activity启动图alg=(lt,n,e,s)、一个返回栈状态中最多能够包含同类型activity实例的个数k作为输入,输出返回栈状态变迁图bstg=(lt,bs,st,bsinit),其步骤如下:

(1)设置集合bs,st为空,待处理节点队列statequeue为空;

(2)构造初始返回栈状态节点bsinit,初始状态只有一个s的实例;

(3)将bsinit加入集合bs,并将bsinit压入待处理节点队列statequeue,然后依次为队列中的每个返回栈状态节点添加出边,亦即activity启动引起的返回栈状态变化和返回动作引起的返回栈状态变化;

(4)弹出statequeue中的队首状态节点currentstate;currentstate栈顶activity实例的类型为cs;

(5)遍历activity启动环中当前activity类cs的出边。对于每条出边,根据表1模拟cs以lt方式启动目标activityct后返回栈状态newstatelaunching;

(6)如果newstatelaunching中的activity重复实例个数不超过k,构造从currentstate到newstatelaunching的边l,并将l加入st。

(7)如果newstatelaunching中的activity重复实例个数不超过k且则将newstatelaunching压入statequeue并加入集合bs;

(8)若currentstate中有超过1个实例,则模拟currentstate顶端元素出栈后返回栈状态newstateback,构造从currentstate到newstateback的边f,并将f加入st;若newstateback不在bs集合中,则将newstateback压入statequeue;

(9)如果statequeue不为空,则跳转到第(4)步。

本发明的优点和积极效果:

本发明方法首先通过启动方式敏感的activity跳转分析生成activity启动图,然后基于activity启动图生成返回栈状态变迁图。activity启动图表示了android应用各activity类间的启动关系,关注于启动方式的提取。返回栈状态变迁图模拟了activity启动和返回动作引起的返回栈状态变化,能够直接表示用户在动态运行android应用时可能出现的返回栈状态。

本发明的优点和积极效果体现在:

(1)对启动方式进行了提取,并模拟了7种以不同启动方式启动activity引起的返回栈状态变化。启动方式不敏感的activity跳转分析假设全部activity均以standard方式被启动。因此对于使用了特殊启动方式的android应用,启动方式不敏感的activity跳转分析无法正确模拟其返回栈状态变化,从而产生非法activity变迁路径,影响基于此的上层应用。启动方式敏感的返回栈状态变迁图则能够在支持多种上层应用(比如gui模型构建、gui测试、漏洞挖掘、缺陷检测等)的同时避免非法路径,以达到积极效果。例如,在基于gui模型的android测试中,使用bstg能够有效避免非法测试用例,提升测试效率,减少人工操作。

(2)通过返回栈状态变迁图,能够发现android应用在被使用过程中一个返回栈状态是否会存在同个activity的多个实例。android应用中,activity启动环在被多次执行后,返回栈中可能产生同类型多个实例。过多同类型activity实例会占用大量系统资源,造成用户使用卡顿,影响用户体验。返回栈状态变迁图能够为android应用开发工程师提供有效信息,以帮助调整activity启动环中activity的启动方式,合理管理返回栈,从而提升软件质量,优化用户体验。

【附图说明】

图1为辅助main()的结构。

图2为android应用软件connectbot的部分代码片段。

图3为启动方式敏感的返回栈状态静态模拟方法的总体框架。

图4为android应用软件connectbot的部分activity启动图。

图5为android应用软件connectbot的部分返回栈状态变迁图。

【具体实施方式】

现结合本发明方法实现对图1的android应用软件connectbot的部分返回栈状态变迁图。本发明所述方法涉及的基本概念:activity启动方式、activity启动图以及返回栈状态变迁图的具体内容详见发明内容部分(此处略)。启动方式敏感的返回栈状态静态模拟方法为connectbot构建bstg的整体框架如图3。具体实现步骤如下:

(1)首先将android安装包反编译后,对生成的中间代码进行预处理,从androidmanifest.xml文件中提取应用包名、activity类集合、mainactivity、各activity的部分返回栈状态相关配置(launchmode和taskaffinity)、各activity能接收的action,然后构建辅助main()以支持对行为驱动的android应用程序的指向分析;(2)对辅助main()进行面向对象的指向分析,并构建activity启动图;(3)基于alg生成返回栈状态变迁图。1.预处理

预处理首先对图2代码片段的androidmainfest.xml文件进行解析:connectbot应用包名为org.connectbot(第26行);第29-30行决定了mainactivity为hostlistactivity;代码片段共包含3个activity类的注册,activity类集合act={hostlistactivity,consoleactivity,settingsactivity}(第27行、第32行和第37行);hostlistactivity和settingsactivity的launchmode属性为空,因此其launchmode为默认值standard,consoleactivity的launchmode属性值为singletop(第33行);三个activity的taskaffinity属性值均为空,因此采用与应用报名相同的默认值“org.connectbot”;只有consoleactivity注册了接收“action.view”动作的能力(第35行),能够对隐式intent发出的“intent.action_view”动作进行响应。

依据图1为connectbot构建的辅助main(),其结构如下:

1voidmain(){

2r1∶=newhostlistactivity();

3r2∶=newconsoleactivity();

4r3∶=newsettingsactivity();

5…

6invokecallback(r1);

7invokecallback(r2);

8invokecallback(r3);

9…}

辅助main()中只包含被重写的回调函数的调用语句。

2.生成alg

对辅助main()依据[rule-1]-[rule-18]的规则进行面向对象的指向分析并生成activity启动图alg=(lt,n,e,s)。辅助main()的第2-4行分别为三个activity类的实例化,android系统为各自对象分配堆内存空间。根据[rule-2],n={o2,o3,o4},即分别为hostlistactivity、consoleactivity、settingsactivity的对象。

图2代码片段的第8、21、11-12行分别调用了组件间通信api。根据[rule-10],该代码片段共有三个启动关系,设代码行8、21、11-12对应的启动关系为e1,e2,e3。这三个启动关系的详细信息如表3所示。e1通过隐式intent对象启动目标activity,该intent对象提供了目标activity需要接收的动作“intent.action_view”(图2第7行),根据[rule-9]和预处理后各activity能够接收的动作,可以确定e1的目标activity为consoleactivity。e1的目标activity的launchmode和taskaffinity值分别为“singletop”和“org.connectbot”,启动目标activity时没有finish()的调用,没有设置intent标志,根据[rule-11]确定e1的启动方式相关配置为有效配置,根据[rule-16]确定e1的启动方式为singletop。e2和e3均通过显式intent对象启动目标activity,分别为hostlistactivity(图2第19行)和settingsactivity(图2第12行)。e2和e3的目标activity的launchmode均为“standard”,taskaffinity均为“org.connectbot”且都没有伴随finish()的调用。e2接收的intent对象设置了标志“flag_activity_clear_top”(图2第20行),e3未设置标志。根据[rule-11]确定e2、e3的启动方式相关配置为有效配置,根据[rule-16]确定e2、e3的启动方式分别standard-cleartop和standard。

表3启动关系详细信息

启动方式敏感的activity跳转分析结束后,所生成的activity启动图alg如图4所示,n1、n2、n3分别表示hostlistactivity、consoleactivity、settingsactivity三个activity类,e1、e2、e3分别表示三个启动关系。alg=(lt,n,e,s),其中:

lt={standard,standard-cleartop,singletop};

n={n1,n2,n3};

e={e1,e2,e3};

s=n1。

3.生成bstg

为图2代码片段生成返回栈变迁图如图5所示,现基于图4的alg说明bstg生成过程。

以activity启动图alg=(lt,n,e,s)作为输入,设置k=2,输出返回栈状态变迁图bstg=(lt,bs,st,bsinit)的步骤如下:

1)设置bs={},st={},statequeue=[],statequeue左侧为队首,右侧队尾;

2)用mainactivity来初始化起始栈状态bsinit=<n1>;

3)将bsinit加入返回栈状态集合bs={bsinit},并将其压入待处理节点队列statequeue=[bsinit];

4)弹出statequeue中的队首状态节点currentstate=bsinit,bsinit栈顶activity实例的类型为n1,此时statequeue=[];

5)遍历alg中n1的出边。n1有两条出边e1和e3。对于

a)当前返回栈状态为bsinit,根据表1第2行模拟n1以singletop方式启动目标activityn2后返回栈状态newstatelaunching=<n1,n2>;

b)newstatelaunching中没有同类型activity实例,构造从currentstate到newstatelaunching的边l1,并将其加入返回栈状态变迁集合st={l1};

c)newstatelaunching中没有同类型activity实例且则将bs2=newstatelaunching压入statequeue并加入集合bs,此时bs={bsinit,bs2},statequeue=[bs2]。

对于

a)当前返回栈状态为bsinit,根据表1第1行模拟n1以standard方式启动目标activityn3后返回栈状态newstatelaunching=<n1,n3>;

b)newstatelaunching中没有同类型activity实例,构造从currentstate到newstatelaunching的边l2,并将其加入返回栈状态变迁集合st={l1,l2}。

c)newstatelaunching中没有同类型activity实例且则将bs3=newstatelaunching压入statequeue并加入集合bs,此时bs={bsinit,bs2,bs3},statequeue=[bs2,bs3];

6)由于当前返回栈状态bsinit中只有一个实例,则不再模拟返回动作引起的返回栈状态变化。

7)此时statequeue不为空,弹出statequeue中的队首状态节点currentstate=bs2,bs2栈顶activity实例的类型为n2,此时statequeue=[bs3];

8)遍历alg中n2的出边。n2有1条出边e2。对于

a)当前返回栈状态为bs2,根据表1第3行模拟n2以standard-cleartop方式启动目标activityn1后返回栈状态newstatelaunching=<n1>;

b)newstatelaunching中没有同类型activity实例,构造从currentstate到newstatelaunching的边l3,并将其加入返回栈状态变迁集合st={l1,l2,l3};

c)由于newstatelaunching=bsinit∈bs,所以无需将bs2压入statequeue。

9)由于当前返回栈状态bs2中有超过1个activity实例,则模拟bs2顶端元素出栈后返回栈状态newstateback=bs1,构造从bs2到newstateback的边f1,并将其加入st,此时st={l1,l2,l3,f1},statequeue=[bs3];

10)此时statequeue不为空,弹出statequeue中的队首状态节点currentstate=bs3,bs3栈顶activity实例的类型为n3,此时statequeue=[];

11)alg中n3没有出边。

12)由于当前返回栈状态bs3中有超过1个activity实例,则模拟bs2顶端元素出栈后返回栈状态newstateback=bs1,构造从bs3到newstateback的边f2,并将其加入st,此时st={l1,l2,l3,f1,f2},statequeue=[];

13)bstg构造结束。

基于alg生成返回栈状态变迁图的最终输出结果为bstg=(lt,bs,st,bsinit),其中:

lt={standard,standard-cleartop,singletop};

bs={bsinit,bs2,bs3},bsinit=<n1>,bs2=<n1,n2>,bs3=<n1,n3>;

st={l1,l2,l3,f1,f2};

bsinit=<n1>。

当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1