本文是论文Understanding and Finding System Setting-Related Defects in Android Apps的总结笔记,作者是Jingling Sun。
总览
安卓系统提供了很多用户可以更改的系统配置,比如网络连接、飞行模式、静音、系统语言等。这些系统配置的变更,可能会影响到app的表现形式。但如果app对这些变更处理不当,可能使app存在缺陷(简称为设置缺陷)。这些缺陷可能引发UI错误、功能失效甚至是崩溃,从而影响用户体验。而目前的软件测试方法并不能系统地找到这些设置缺陷。
本文主要从两个方面研究设置缺陷:一方面,本文收集了180个开源安卓app的1074个设置缺陷,并探究它们的影响(impact)、根本原因(root causes)和后果(consequence)。另一方面,构建了一个端到端的测试工具(SetDroid)对26个流行的开源项目进行测试,并找到了42个设置缺陷(33个被确认,21个被修复)。同时,对5个流行的工业软件开展测试,找到了17个设置缺陷(全部被确认和修复)。
本文的核心思想是,所有的软件应该针对系统设置的变化,自动地做出相应的改变,并且:
- 系统设置还原后,能够恢复到原来的状态。
- 在不还原的情况下,能够体现出不同设置下的差异。
以实际的app为例,来解释设置缺陷是如何引发错误的:
-
Wordpress
- 当用户在发表一篇博客时开启飞行模式,则发送的操作会一直保持在等待状态,即使飞行模式已经被关闭且网络恢复了。
- 在飞行模式下发送草稿后,app将会在下一次开启时崩溃。
-
NextCloud
在用户开启了系统的省电模式后,它的自动上传功能会变得无法使用,即使用户已经把app加入了省电模式的白名单。
目前的方法中,大多没有系统地研究这些缺陷,而是专注于某些特定的系统设置(如权限、屏幕方向)。另外,一些SOTA的通用测试技术只在app内部做测试,很少考虑到系统设置的影响;或是只研究引发程序崩溃的缺陷,而没有探测那些不会引发崩溃的缺陷(non-crash defects)。所以本文的工作亮点为:
- 针对大部分的系统设置进行研究
- 考虑系统设置对app的影响
- 不仅检测引发崩溃的缺陷,还检测不会引发崩溃的缺陷
为了达到这些目的,本文主要针对三个研究问题进行探究和分析:
- RQ1(impact):设置缺陷是否会广泛影响app的使用?
- RQ2(root cause):引起这些缺陷的主要原因有哪些?
- RQ3(consequences):这些缺陷主要引发什么后果?这些后果是以什么形式展示的?
经验研究方法
收集和总结设置类别
本文根据安卓文档和主流的安卓系统,总结了9个主要的设置类别,并使用一些常见的关键词来描述它们。这些关键词从一些bug报告和安卓SDK API中提炼而来,具体关键词如表所示:
Setting Categories | Keywords | Description |
---|---|---|
Network and connect | Bluetooth, WLAN, NFC, internet, network, hot-spot, mobile, wifi, airplane | 管理设备的网络模式(Wi-Fi、移动数据或飞行模式)或是和别的设备的连接(蓝牙) |
Location and security | location, device only, phone only, GPS, high accuracy, screen lock, fingerprint | 管理设备的安全设置(如何解锁)、定位及对应的三种定位方式(使用网络和GPS、只使用网络、只是用GPS) |
Sound | vibrate, ringtone, do not disturb, silent | 管理设备的声音(如禁音状态) |
Battery | power save, battery | 管理省电模式,或为各app加入省电模式白名单 |
Display | orientation, vertical, horizontal, split screen, Multi-window, screen resolution, brightness, landscape, portrait, rotate | 管理设备的显示,如亮度、字体和屏幕方向 |
Apps and notifications | permission, disable, notification | 管理运行时的权限、以及app是否能够给用户发送通知 |
Developer | developer option, keep activity | 模拟特定环境的告诫设置,如强制right to left布局方向 |
Accessibility | accessibility, talkback, text-to-speech, color correction, color inversion, high contrast text | 辅助功能,如调整对比度、打开屏幕阅读器 |
Other settings | setting, preference, date, time, time zone, hour format, date&time, reading mode, car mode, one-handed mode, dark mode, game mode, night mode, theme, language | 改变语言、系统时间、输入方式、系统时间格式、主题等 |
收集设置缺陷的bug reports
收集设置缺陷的bug reports分为三个阶段:
-
App收集
基于Github收集开源安卓App,使用他们的源代码、错误和缺陷的描述、复现步骤、修复补丁和话题讨论。具体来说:
- 使用Github的REST API获取所有的安卓项目,并选取在Google Play和F-Droid上架的App,最终收集到1728个项目。
- 选取包含200个以上已被Closed的issues或bug reports的项目,筛选出215个项目。
- 人工筛除其中的第三方库(这些库的demo上架了商店),最终筛选出180个项目。
- 对收集到的项目,用箱型图描述了Star和Issue个数的分布,并统计它们的安装次数和项目类别。结果显示,收集到的项目覆盖了多个热门程度和软件类别。
-
问题报告(Bug Reports)收集
本文从180个app中收集了177,769个问题报告,基于三个关键词集,筛选出包含这些关键词的问题报告
- 设置关键词(Setting keywords):至少包含表格中一个关键词的问题报告,这些关键词可以是大写、缩写和不同时态的。
- 缺陷或失败的关键词(Defect/failure keywords):包含crash、exception、bug、issue关键词的问题报告,表明该问题报告用于描述app中出现的问题。
- 复现关键词(Reproducing keywords):使用关键词”repro“、”STR“、”record“来筛选问题报告,这些关键词表明问题报告中包含一些问题的复现步骤,这样可以帮助我们确认这些它是否涉及设置缺陷,也可以让我们定位到缺陷出现的原因。
通过该步骤,总共筛选出了11,656个问题报告。
-
数据集构建
为了回答三个研究问题,本文人为地检查了11,656个问题报告,并按照以下两个规则进行筛选:
- 报告人或开发者明确指出,更改系统设置是引发问题的必要条件。
- 对于没有明确线索的问题报告,本文复现了这些步骤来确定它是否和设置缺陷相关,同时也剔除了那些只包含“设置”字眼的问题报告。
最终,本文筛选出1,074个问题报告作为数据集,其中482个已经被修复并关闭。每个问题报告都反映了某种设置缺陷。
对于各研究问题的分析方法
为了提升研究的准确性和客观性,本文的4位作者都参与了数据收集、分类、人工分析和交叉验证的过程。
-
对于RQ1,本文重点关注的是:
- 每个软件使用中所涉及的系统设置,即各种系统设置对软件的影响程度。
- 每个软件设计哪些设置缺陷,即设置缺陷对软件的影响程度。
在移动端开发中,SDK会为开发者提供每种系统设置涉及的类、方法、变量和回调函数等接口。通过统计开源软件中这些接口的使用情况,来判断这些软件是否有依赖于系统设置。
-
对于RQ2,本文重点关注的是482个已被修复的问题报告,从中提取出产生问题的根本原因和解决方法。
-
对于RQ3,针对1,074个问题报告,分析它们产生的后果,并且在需要的时候复现这些问题来观察结果。
对于研究问题的分析结果
RQ1:设置缺陷的影响
如上文所述,对于此问题,本文聚焦于:
- App中对于设置的使用情况
- 设置缺陷对app的影响
本文基于180个筛选后的app,为每种设置类别统计了
-
涉及各种设置类型的app数量(Apps using settings):
当软件使用了某种设置类型的API,则认为它涉及了该设置类型,此处一个软件可能涉及到多个设置类型。值得一提的是,有些没有显式的API的系统设置(如Developer和Accessibility)没有被统计进去,故此处的统计结果是一个下限值。
-
受到设置缺陷影响的app数量(Apps were affected):
当软件的对应的bug reports中提到了某个设置类型的关键词,则认为这个软件受到了这种设置缺陷的影响。
-
设置缺陷数(Setting Defects):
对于所有bug reports,检查它们描述中所涉及的是哪一个设置类型,并为每个设置类型统计数量。
设置类型(Setting categories) | # Apps using settings | # Apps were affected | # Setting Defects |
---|---|---|---|
Network and connect | 86 | 68 | 326 |
Location and security | 47 | 10 | 14 |
Sound | 67 | 16 | 50 |
Battery | 57 | 10 | 18 |
Display | 109 | 78 | 226 |
Apps and notification | 134 | 49 | 121 |
Others | - | - | 319 |
# Total | 171 | 162 | 1,074 |
表格中,App using settings和Apps were affected的Total行表示所涉及的app总数,并不是单纯的将该列相加。通过表格我们可以观察到以下情况:
- 95%(171/180)的软件涉及到了至少一种设置类型,这些类型中”Apps and notification”的数量最多,因为大多软件都涉及到了权限使用和通知。
- 大多数的软件都至少受一种设置缺陷的影响,占比达到了90%(162/180)。其中“Display”、“Network and connect”、“Apps and notifications”的影响范围最广。
- 在所有的设置缺陷中,“Display”、“Network and connect”、“Apps and notifications”类型出现的最多,因此这些设置类型最容易引发设置缺陷。
RQ2:引发设置缺陷的根本原因
本文分析了482个已修复的bug reports,并总结了几种常见的引发原因:
Root causes | # Bug Reports |
---|---|
回调函数实现不当(Incorrect callback implementations) | 164 |
缺少对设置的检查(Lack of setting checks) | 143 |
没有适配用户界面(Fail to adapt user interfaces) | 103 |
没有考虑安卓版本(Lack of considering Android versions) | 27 |
多个设置之间的影响(Mutual influence between settings) | 12 |
其它 | 33 |
-
回调函数实现不当:
当系统设置发生改变时,程序会调用相应的回调函数,如果这些回调函数中没有处理好相应的逻辑,可能会引发错误。
如AnkiDroid中,当用户请求存储权限的时候,屏幕右上角菜单中的按钮会消失,在用户完成请求后,应该要重新绘制这个按钮。
-
缺少对设置的检查:
当某些设置影响到软件的功能时,开发者应该在实现这些功能时检查这些设置的状态,否则当设置变更时,软件并不会发生相应改变。
如NextCloud中,自动上传功能是否开启取决于系统是否进入省电模式。而安卓系统中省电模式拥有白名单功能,在白名单内的软件并不会受省电模式关闭的影响。而NextCloud只判断了系统是否进入省电模式,而没有判断软件是否在白名单内。因此即使软件在白名单中,还是无法开启自动上传功能:
-
没有适配用户界面:
一些设置(如多窗口模式、系统语言、字体大小、dark mode等)会影响UI布局,如果app不能很好的适配这些改变,则会引发界面显示问题(组件显示不全、文本重叠等)。另外本文观察到,这些问题大多可以通过修改XML布局的方式解决,而不是修改源代码。
-
多个设置之间的影响:
一些设置之间可能存在显式或隐式的影响,比如定位功能可以通过GPS或网络、或是两者同时实现。
一个显式的例子是,在Common中,如果在离线状态下打开app会引发崩溃,因为它在启动时通过网络来获取定位,在离线状态下这个函数会返回NULL值,这个值会被另一个获取定位的函数使用,从而引发崩溃。
一个隐式的例子是,当省电模式开启时,定位、网络和动画的功能会被影响,比如Clover在省电模式中,某个动画会被自动关闭,从而引发线程阻塞,使得软件崩溃
-
没有考虑安卓版本:
不同版本的安卓系统拥有不同的机制,比如某些版本中,对于一些功能可能会有额外的权限要求,如果没有加以控制会引发程序崩溃。
比如OpenLauncher中,当勿扰模式开启时会引发崩溃,因为在Nougat版本中,开启勿扰模式时会调用AudioManager的方法,而在调用该方法前需要获得ACCESS_NOTIFICATION_POLICY权限,故此时需要提前检查安卓的版本来考虑是否获取权限。
RQ3:设置缺陷引发的后果
本文从1,074个bug reports中总结了四种主要的后果:
-
崩溃(315条):
崩溃是占比最大的后果,一些软件崩溃可以通过重启解决,一些则无法解决,只能重新安装软件。
如在OpenFoodFacts中,当系统切换到海地语后,软件再也无法打开。
-
不响应设置变化(285条):
在设置变化后,软件并没有做出相应的改变。主要原因是开发者并没有考虑到一些设置改变带来的后果,所以没有做相应的适配。
如Signal中,当用户打开勿扰模式后,该软件的通知仍然会发出声音。又如一些软件在更改系统语言后,内容不会翻译或是只有部分翻译。
-
UI显示问题(218条):
在改变一些影响显示的设置(如语言、主题)后,软件并不能正确地展示UI。
如邮箱软件K-9,当用户切换到黑暗模式后,邮件内容引用部分的字体依然保持黑色,导致用户无法看到其中的内容。
-
功能不可用(197条):
当某些设置改变后,软件中的一些功能并不能达到预期的效果。同时,由于开发者没有意识到这些问题的原因,不会对该现象给出提示,或是会给出一些令人困扰的提示,影响用户的使用。
如syncthing中,当省电模式开启时,会导致后台同步功能无法使用,而syncthing没有提示用户省电模式会对同步功能造成影响。
类似的情况还有app卡死、黑屏、无限读取、无法刷新等问题。
检测app中的设置缺陷(基于SETDROID)
蜕变模糊测试
对于一个常规的测试用例,由测试输入(test input)和预期输出(test oracle)组成,但是很多情况下,预期输出是很难获得的(oracle problem)。
-
蜕变测试(Metamorphic testing)基于已有的测试输入,构建新的测试输入,并且新旧输入应当有相同的输出。通过对比原始输入和构建输入的两个输出,来判断程序是否出现错误。
-
模糊测试(Fuzzing testing)指自动地或半自动地生成随机的测试用例作为程序的输入,来测试程序是否出现问题。
本文基于模糊蜕变测试的思想,随机生成对app的操作序列$E$(体现模糊测试的思想),并在操作序列$s$中随机插入事件$<e_c,e_u>$构成新的操作序列$E’$,其中$e_c$改变了系统设置,$e_u$可能还原系统设置,也可能什么也不做。本文验证app在$E$和$E’$下的表现是否一致(体现蜕变测试的思想)。
根据本文的核心思想:
- 当$E$插入改变事件$e_c$和还原事件$e_u$,构成$E’$后,$E$与$E’$的表现应该是一致的。
- 当$E$进插入改变事件$e_c$,构成$E’$后,$E’$的表现应该与$E$有期待中的差异。
具体来说,操作序列$E$由一系列的用户操作构成(比如点击、编辑、扫屏、旋转屏幕等),我们用$E=[e_1, e_2,\dots,e_n]$表示。
$E$中的每一个事件都会使GUI的状况发生改变,我们用一个GUI分布序列$L$来表示GUI对应的变化情况:$L=[l_1, l_2,\dots,l_{n+1}]$,其中$l_i$表示在$e_{i-1}$操作后,GUI中的组件(widget)分布。
当在$E$中插入事件$<e_c,e_u>$后,得到的事件序列表示为$E’=[e’_1,\dots,e_c,\dots,e_u\dots,e’_n]$,同时对应的GUI分布序列$L=[l’_1, l’_2,\dots,l_c,\dots,l_u\dots,l’_{n+1}]$。
对于每个事件$e$,它对某个GUI组件$w$进行操作(比如事件$e$点击某个按钮$w$),我们把这种关系记为$e.w$。
通过比较$L$和$L’$的关系,对“改变设置”这一行为造成的影响进行分析。具体的比较规则有两个规则:
-
规则1: 使用两种策略,将$<e_c,e_u>$插入到$E$中:
- 立即修改(Immediate setting mutation):在执行$e_c$后立即执行$e_u$,如在开启省电模式后立刻将app加入省电模式白名单。
- 懒修改(Lazy setting mutation):在执行$e_c$后,只在必要的时候执行$e_u$,比如关闭了软件权限后,仅在软件再次申请权限时允许。这种行为也是符合安卓用户体验设计规范的。
若对于$E’$中的某个$e’_i$,存在$e_i’.w$不在$l’_i$中,则判定其存在设置缺陷。
-
规则2:只将$e_c$插入到$E$中,用于验证在设置改变后,两个GUI序列是否能有期望的差异。如使用langid(一种语言区分工具)来判断在改变系统语言后,软件的语言是否发生改变。
SETDROID的设计和实现
本文设计了一个自动化GUI测试工具SETDROID,主要包含4个模块:
-
测试执行器(test executer)
基于两个相同的设备A和B,同时执行以下步骤:
- 获得当前的GUI分布
- 随机选择一个可触发事件的组件,并生成事件
- 执行该事件
这里使用了UI Automator test framework来执行事件和获取GUI分布。
-
设置变化注入器(setting change injector)
根据本文的研究发现:
- 43.4%的设置缺陷,是由于在软件执行过程中改变设置引发的(而不是在开启软件前)
- 只有2%的设置缺陷是由于多个设置改变而引发的(其中主要是屏幕旋转和其它设置同时改变时,会引发问题)
所以在该模块中,注入器随机在运行过程中注入单个事件$<e_c,e_u>$,如果没有产生影响,则过段时间后再随机注入,直到事件序列结束。具体注入的事件如表所示,这些事件都是根据经验选取得出的:
-
测试输出检查器(oracle checker)
在测试执行器的每次执行操作后,输出检查器根据规则1和规则2来检查两个设备的状况是否符合预期。
-
问题报告生成器(bug report reducer)
一旦输出检查器发现缺陷,则报告生成器会进行执行以下步骤:
- 检查这个缺陷是否已经被记录,若已经记录则抛弃,否则执行b。
- 根据该缺陷的事件序列进行多次复现,若能够稳定发生缺陷,则执行c。
- 记录该缺陷的事件序列和缺陷截图。
本文将发生缺陷时的GUI分布生成为哈希编码,在步骤a中通过比较哈希编码来确定缺陷是否被记录。
SETDROID为每个app随机生成20个测试序列(每个序列包含100个事件),并在序列中插入13个事件对。每个app的每个事件对,需要花费1小时时间执行,于是总共需要13*26=338个小时执行。
评估SETDROID
本文通过解决两个问题,来对SETDROID的成效进行评估:
-
RQ4:SETDROID能否监测到未曾发现过的设置缺陷?
本文选取了之前工作中使用的30个流行开源软件,并筛选出其中26个保持活跃的软件进行评估。根据记录的所有问题报告,人为地标记处True Positive(真实的软件错误)和False Positive(被误判的软件错误)。当发现某个TP可以复现,并且没有被在issues中被报告后,作者将它们的复现步骤和视频在issues中提出。
同时,本文在5个工业软件(微信、QQ邮箱、TikTok、CapCut和支付宝HK)中进行测试,花费2天时间进行缺陷检测。
从结果来看,SETDROID具有如下特性:
-
有效性:在26个软件中,SETDROID发现了42个未曾被检测到的设置缺陷,其中33个被证实为缺陷,21个被修复,体现了SETDROID的有效性。
-
可用性:对于规则1,83.2%(124/149)的设置缺陷被认定为真实的缺陷,未被认定的缺陷(FP,16.8%)是由于某些软件在设置变化后,会引发一些弹窗提醒等动画,所以产生了GUI不一致的情况;对于规则2,19.2%(127/662)的设置缺陷被认定为设置缺陷,未被认定的缺陷(FP,91.2%)皆为英文阅读软件,所以当改变系统语言时,文章的内容并不会被翻译,从而产生了大量的FP。但对于一些GUI上未被翻译的内容,SETDROID可以快速的识别出来,同时通过可以在检测时忽略一些特定的组件(如文章内容),来避免产生这样的情况
-
缺陷的多样性:SETDROID在多个软件中,检测到了多种类型的设置缺陷,以及多种缺陷后果。
-
实用性:在工业软件中,SETDROID检测出了17个设置缺陷,并且全部被对应的公司修复,这些缺陷也是不同模块引发的不同结果。
-
-
RQ5:SETDROID能否找到现有工具无法找到的设计缺陷?
现有的测试工具可以分为两种:
- 通用测试工具:专注于app内部的测试,没有和系统设置交互
- 专用测试工具:专注于某些软件问题进行检测
其中,PREFEST对于偏好设置引发的缺陷进行检测,同时也考虑一些系统设置(蓝牙、网络和定位);PARDROID考虑了权限设置。这些工具都只能检测到引发崩溃的缺陷。
本文涉及了两个方式来和这些工具做对比:
- Baseline A(随机测试):随机生成事件序列(即SETDROID中的测试执行器模块)。
- Baseline B(随机测试+改变设置):参考PREFEST和PARDROID的测试方法,在测试的开始改变某些设置,再执行随机的事件序列。
本文在26个开源项目中,对SETDROID在两个基线上进行对比,同时也对三个工具进行横向对比:
- 在考虑所有设置的情况下,有:
- 直接进行Baseline A测试,不会发生错误。
- 执行Baseline B,会发现3个崩溃错误。
- 使用SETDROID,会发现9个崩溃错误和33个非崩溃错误。
- 在考虑蓝牙、网络和定位设置的情况下,有:
- PREFEST没有发现错误。
- SETDROID发现10个非崩溃错误。
- 在考虑权限设置的情况下。有:
- PARDROID发现2个崩溃错误。
- SETDROID发现6个崩溃错误和8个非崩溃错误。
效度威胁
本研究的效度威胁主要在于所研究的软件是不具有代表性。在本文中,对于设置缺陷的分析,本文从1,728个开源软件中选取了180个进行研究,这些软件覆盖了大部分的软件类型;对于SETDROID的验证,本文选取近期工作中被大量使用的,26个活跃的开源软件,以及热度很高的工业软件开展试验。
另一个主要的效度威胁是设置关键词不完整,从而导致收集到的设置缺陷不完整。本文从安卓官方文档中尽可能地收集设置相关的关键词,同时考虑到了这些词语的不同时态等因素。
最后一个效度威胁是人为判断的主观性。本文的4个作者通过交叉验证的方式,对检查结果进行分析,从而保证了结果的准确性。