APP加载错误导致FM打开失败

【背景介绍】

不做FM好多年,记得还是在多年前,完整写过FM从上层调用逻辑到底层驱动,按照标准的软件开发流程来操作,输出需求分析、概要设计、详细设计、编码、测试、交付。当时的目的是为了实践软件开发的完整流程,拿FM练练手。

这次遇到的FM问题,帮忙性质更多些,自己接到这个问题的时候心里并没有底,但本着对自己的信心,想一探这个“难”问题的玄机。

 

【问题描述】

产线在批量生产时,发现有40%-60%的手机在开机做工程模式测试时,打开FM失败,由于概率很高,Block产线生产。

 

【问题分析】

1,整理问题历史和实验数据:

Deadline

我接到此问题时,已是5.25(周三)中午,PM要求5.31(周二)前必须解决,否则直接影响到6月初的生产安排。意味着我只有4个工作日的时间,解决一个当前毫无头绪的复杂问题,有压力。

历史和数据

要求将关于此问题的所有历史邮件转给我,完整阅读后,我直接找到原来的Owner面对面做了交接,了解之前的分析进展和弯路。

整理如下:

a)从某版本之后概率似乎变高,其中有两个版本概率达到40%以上:所以,就用这个版本分析了;

b)同软件基线的另一项目似乎没有问题,测试压力测试后,似乎偶尔能复现,但FM过几秒后能正常工作,没有这个产品完全不能使用的情况;

c)最早怀疑是FM APP的问题,因为平台默认的APP没有这个问题,但FM APP的同事从log中发现是底层在报错,因此转给底层的同事分析;

04-08 16:19:36.170 11440 11841 E         : FmIoctlsInterface: ioctl call failed                                 #I/O通 道驱动失败
04-08 16:19:36.170 11440 11841 E android_hardware_fm: android_hardware_fm: set calibration failed

04-08 16:19:37.732 11440 11841 E FMRadio : enable: Error while turning FM On

d)底层的同事认为较早的软件版本没有问题,似乎从FM APP更新至某版本后比较容易出现异常,且经咨询平台支持人员,从经验来说是APP加载错了lib导致

in logcat log suggests you may use wrong FM JNI lib. pls check your if your FM APP is of 32 or 64 bits, and it should use lib in /system/lib or lib64 correspondingly.

 

2,我从上述b)中所提到的同基线项目复现概率有差异入手,寻找突破口,同时,也为了调动测试部门的资源,帮助我开拓一些线索,因此,尝试如下:

(1)排查出问题的lib库文件

排查两点:

a)调用文件是否一致:确认和平台自带APP所调用文件一致;

b)库文件是否有篡改:没有,完全和平台模式自带的库文件一致,并且正常和异常时的库文件也一样;

(2)从log看到,明显JNI和HAL处报错,因此排查HAL和JNI的调用逻辑,没有发现异常;

(3)鉴于同基线另一个项目不容易复现,而这两个项目硬件上的区别能想到的有两个

a)走线

b)RAM大小不同

因此,请测试用相同RAM的手机3台,各做30次,观察概率,最终的结果是相同RAM大小的测试机也不能复现,说明和RAM大小无关

 

3,尝试在FM APP中指定加载64位JNI LIB,但运行报错,原因是,APP加载为32位,不允许调用64位库文件

05-26 15:33:06.130  7121  7121 W System.err: java.lang.UnsatisfiedLinkError: dlopen failed: "/system/lib64/libqcomfm_jni.so" is 64-bit instead of 32-bit
05-26 15:33:06.130  7121  7121 W System.err:      at com.android.mmi.Fm.<clinit>(Fm.java:123)

 

4,检查为什么FM APP会被加载为32位,原因怀疑有两个:
(1)APP未指定ABI:尝试在FM APP中指定ABI,但不奏效,说明不是这个原因;
(2)共享UID动态调整:去除adjustCpuAbisForSharedUserLPw,异常消失,锁定原因,并有了一个临时的解决 方案,但仍有疑问:被共享的system_server加载出错?还是其他共享uid为system的其他APP的影响?(APP中android:sharedUserId="android.uid.system")

 

插曲:由于share uid的方向出来后,有同事提到另一个APP似乎有导致其他APP加载32位的情况,结果浪费了一天的时间排除了这个APP的影响

 

 

 

5,尝试去除share uid动态调整ABI加载后(PackageManagerService中adjustCpuAbisForSharedUserLPw),问题不复现了,看到曙光了!但是这还不是root cause,最终也不能这么改,而且system server加载成了32位呢?什么导致误加载的呢?

 

 

6,在/data/system/packages.xml中查看android.uid.system,其uid为1000

<shared-user name="android.uid.system" userId="1000">

因此,检查所有共享uid为1000的APP,尤其关注那些非系统或项目共用的APP,发现一个FOTA APP特殊,进而检查其APK中打包的lib,发现只有32位的so和odex文件

<package name="com.c.dmclient" codePath="/system/app/DMClient" nativeLibraryPath="/system/app/DMClient/lib" primaryCpuAbi="armeabi-v7a" publicFlags="940097101" privateFlags="0" ft="154b0e0d7f0" it="154b0e0d7f0" ut="154b0e0d7f0" version="1" sharedUserId="1000">

 

7,尝试去除此可以APP DMClient,验证正常,反之,在那个不会复现的项目上导入此可以APP DMClient,能够复现异常,因此,锁定为此APK的影响;

小结:

a)此APP DMClient只用于出现异常的项目,而其他项目没有此APK,因此解释了为什么共基线的另一个项目没有问题;

b)关于概率性出现异常,即有时开机FM是正常的,这可能是由于adjustCpuAbisForSharedUserLPw具有一定的随机性引起的;

总的来说,APP以什么方式启动,有如下3各层级的逻辑:

首先,APP通过ABI指定,PSW会扫描;

其次,交由系统定义的CPU ABI决定默认启动方式;

最后,由共享UID调整机制做动态调整

 

这就要求APP严格注意兼容性和规范性:
(1)    将shareuser apk使用到的lib都编译成两套;
(2)    尽量将apk私有lib,打包到自己的lib abi目录,通过PMS扫描到正确的模式,并且是针对ABI优化过的;

 

【问题原因】
FOTA APP只打包为32位,即只能以32位方式运行,导致PackageManagerService中adjustCpuAbisForSharedUserLPw根据共享UID(system)调整APP加载为32或64位时,受到共享uid为system的影响,导致相同共享system uid的APP均以32位加载(不仅仅有FM APP)。而FM 打开时的Calibration动作所发数据格式只能以64位JNI lib执行,否则会有数据不匹配,从而底层产生timeout错误,JNI中显示FmIoctlsInterface: ioctl call failed
 
【解决方案】
1,最根本的修改方法是,FOTA APK做64位解决兼容性问题,并将私有lib放到相应abi目录下(arm64-v8a),但在项目临近关键节点时做此改动,牵涉到FOTA功能是否稳定的问题,并且重测也需要时间,这是有风险的;

 

2,调整共享uid的调整机制,在其中排除32位FOTA APP加载导致的调整

 

 

【我的收获】

1,通过这个问题的分析,接触了新的东西,包括ABI,APP动态加载,以及相关的分析方法;

2,在整个问题的解决过程中,其实在定位到share uid时,我已经可以放弃了,转给相应的软件小组分析即可,但是我想这是个学习的机会,虽然是自己不熟悉的领域,一边学习,一边分析,并向相关的同事请教,最终达成解决。所以,自我驱动很重要,把每一个问题当成学习的机会,对自己也是成长。

3,在PM指定的时间点前完成了此问题,收获了成就感,当然,也加了周六周日两天班,连续工作两周;

附打卡时间,记录艰苦岁月 :)

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值