aosp12 framework重大bug:contentprovider获取低概率偶现延时10s问题修复经验分享

news/2024/11/28 11:46:07/

问题背景:

在android12的版本上,陆陆续续发现一个低概率偶现的问题,那就是桌面第一次启动会存在显示空白10s以上,正常空白一般在1-2s,在个空白10s以上确实就属于非常严重的问题,但这个是一个低概率偶现问题,而且只有一例,所以说一直也没有引起重视。直到陆续确实有测试都报有这个同样问题,这个时候就开始要着力重点解决,这里分享一下针对这种低概率偶现问题的处理方式,这种方式适合所有framework端的一些低概率的偶现问题解决。
更多framework干货知识手把手教学

Log.i("千里马qq群",“422901085);

framework层面低概率偶现问题处理方法

这里主要分享一下公司里面是如何处理低概率偶现问题的:
1、需要在对应的怀疑地方加追踪日志,等待下一次测试复现时候可以有更多的log依据
2、如果概率较高,比如可以几十次复现一次,那么就需要组织测试人力进行集中复现该问题
3、只要可以概率复现,和测试合作复现,就不断的加日志缩小范围,追踪到根本原因
4、知道了根本原因后,考虑修改代码故意触发错误,然后让问题必现,看看现象是否和低概率问题一致
5、确定波及最小的修改问题方案进行修改,修改后验证可以先考虑让代码故意触发bug看看是否 修改已经生效,然后再去除故意触发bug代码,提交给测试验证测试

contentprovider的具体问题揭秘

首先来看看android 12上的acquireProvider代码:

@UnsupportedAppUsagepublic final IContentProvider acquireProvider(Context c, String auth, int userId, boolean stable) {final IContentProvider provider = acquireExistingProvider(c, auth, userId, stable);if (provider != null) {return provider;}ContentProviderHolder holder = null;final ProviderKey key = getGetProviderKey(auth, userId);try {synchronized (key) {//这里从ams查询又没有改providerholder = ActivityManager.getService().getContentProvider(getApplicationThread(), c.getOpPackageName(), auth, userId, stable);//如果没有查询到provider,那么就需要等待ams发布provider即notifyContentProviderPublishStatus执行if (holder != null && holder.provider == null && !holder.mLocal) {synchronized (key.mLock) {//注意这里加锁进行下面操作//注意这里就有wait 10s的操作key.mLock.wait(ContentResolver.CONTENT_PROVIDER_READY_TIMEOUT_MILLIS);holder = key.mHolder;}if (holder != null && holder.provider == null) {// probably timed outholder = null;}}}} //省略return holder.provider;}
//ams端回调app进程通知provider已经准备好了@Overridepublic void notifyContentProviderPublishStatus(@NonNull ContentProviderHolder holder,@NonNull String authorities, int userId, boolean published) {final String auths[] = authorities.split(";");for (String auth: auths) {final ProviderKey key = getGetProviderKey(auth, userId);synchronized (key.mLock) {//注意这里进行对应的mHolder设置填充key.mHolder = holder;key.mLock.notifyAll();}}}

乍一看好像代码没有问题,代码想要实现流程如下:
在这里插入图片描述

但是为啥有会有这个等待10s问题,而且等了10s后确实有相应的provider值
问题关键,多线程并发,没有注意锁的范围控制:
在这里插入图片描述

同时看看notifyContentProviderPublishStatus的锁也是这个key.mLock

 public void notifyContentProviderPublishStatus(@NonNull ContentProviderHolder holder,@NonNull String authorities, int userId, boolean published) {//省略synchronized (key.mLock) {key.mHolder = holder;key.mLock.notifyAll();}}

但是呢?大家看看
在这里插入图片描述

那么也就存在可能

     holder = ActivityManager.getService().getContentProvider(getApplicationThread(), c.getOpPackageName(), auth, userId, stable);

这一行代码查询时候确实没有,但是查询完了后如果多线程产生并发notifyContentProviderPublishStatus又同时执行了,那么notifyContentProviderPublishStatus先获取了mLock,而且给provider赋值了,导致自己的mLock就再也不会有notifyContentProviderPublishStatus来解锁

 synchronized (key) {holder = ActivityManager.getService().getContentProvider(getApplicationThread(), c.getOpPackageName(), auth, userId, stable);if (holder != null && holder.provider == null && !holder.mLocal) {//查询完成后,还没有执行下面的代码,马上有ams回调执行了notifyContentProviderPublishStatus,导致了这个key.mLock执行在notifyContentProviderPublishStatus后面synchronized (key.mLock) {key.mLock.wait(ContentResolver.CONTENT_PROVIDER_READY_TIMEOUT_MILLIS);holder = key.mHolder;}if (holder != null && holder.provider == null) {// probably timed outholder = null;}}

那么问题就明白了相当于本质其实就是锁范围不对,导致了这个10s问题

解决方案

这里为了最小的波及范围,不采用修改锁的范围方式,采用如下检测修改方案

 synchronized (key) {holder = ActivityManager.getService().getContentProvider(getApplicationThread(), c.getOpPackageName(), auth, userId, stable);if (holder != null && holder.provider == null && !holder.mLocal) {synchronized (key.mLock) {if (key.mHolder== null) {//这里需要加个再判断是否这个mHolder还为null,才进行等待key.mLock.wait(ContentResolver.CONTENT_PROVIDER_READY_TIMEOUT_MILLIS);}holder = key.mHolder;}if (holder != null && holder.provider == null) {// probably timed outholder = null;}}

发现aosp 13已经有官方修复的patch,和上面修改方案差不多:
在这里插入图片描述


http://www.ppmy.cn/news/165400.html

相关文章

第六章 数组、排序和查找

一、数组(P156) 1. 数组介绍 数组可以存放多个同一类型的数据。数组也是一种数据类型,是引用类型。 即:数(数据)组(一组)就是一组数据。 2. 数组的使用 2.1 使用方式1:动态初始化 数组的定义: 数据类型 …

我的LG液晶显示器电源灯怎么不亮了?

请教大家 我买了三个多月的一款LG52ST的 液晶电脑显示器电源灯为什么亮一下它自己又不亮了 ?举例来说,如果开两个传奇游戏,从一个游戏画面切换到另一个游戏画面是它又会亮一会儿,然后不亮,这是为什么?恳请大…

LG GP750 显示器评测

LG GP750 采用了 31.5 英寸的 IPS 面板,2560 x 1440 分辨率,165Hz 刷新率,400 尼特典型亮度,拥有 DisplayHDR 400,99% sRGB 色域,1ms GTG 响应时间。 LG GP750更多使用感受和评价 http://www.adiannao.cn/d…

中韩几大电视机制造商的液晶面板采购订单从第二季度开始将出现强劲反弹 | 美通社头条...

美通社消息:根据Omdia电视显示和OEM资讯服务,期待已久的全球顶级韩国和中国电视制造商液晶电视面板订单需求复苏即将到来。Omdia预计2023年第二季度将出现19%的强劲反弹,预计50英寸和更大尺寸的屏幕订单将达到1.614亿台或同比增长8%。如果202…

基于P-Tuningv2轻量微调和推理chatglm

类ChatGPT的部署与微调(下):从GLM、ChatGLM到MOSS、ChatDoctor、可商用_v_JULY_v的博客-CSDN博客随着『GPT4多模态/Microsoft 365 Copilot/Github Copilot X/ChatGPT插件』的推出,绝大部分公司的技术 产品 服务,以及绝大部分人的工作都将被革…

LG gram 2023款 评测

LG gram 2023 将会搭载英特尔 13代酷睿新品,而且配备 RTX 3050 独显,支持 VRR 可变刷新率。 在本月初的 CES 2023 上,LG 面向全球推出这款笔记本电脑,包括全新 gram Ultraslim 和 gram Style,国行定价暂未可知。 LG g…

lg显示器工厂模式怎么进入_LG液晶显示器进入工厂模式方法.概要

显示器工厂模式的进入方法集锦 1.TCL 显示器 1 ) M1502 显示器 面板按键:“-”,“+”,“←”,“→”,电源开关“◎”。 工厂模式:首先关闭显示器电源开关,再同时按住“-“与”→”不松手,打开显示器电源开关,当显示器屏幕 出现图像时松开手,这时即进入工厂模式,屏显 …

显示屏

1、LCD (Liquid Crystal Display) 1888年莱尼泽(Friedrich Reinitzer)从植物中提炼出一种称为螺旋性甲苯酸盐的化合物,加热具有两个不同温度的熔点,在某一温度范围内却具有液体和结晶双性质的物质&#xf…