AOSP Settings模块问题初窥
本文来源于本人在工作组内分享,源码、公司部分以做加密、模糊处理,旨在分享在Android中对于Settings设置模块的问题分析思路、案例分析等。
目录
一、实际常用工具
ADB常用命令
Jadx 反编译工具
grep、find搜索文件/代码
HierarchyViewer
MediatekDBViwer
编辑
DB常用文件说明
二、问题分析思路
问题分析思路
编辑
UI类问题
需求类问题
功能类问题
ANR问题
三、典型问题案例
从简单UI问题举例
固定拨号列表界面无法横屏
无障碍功能菜单,点击设置,底部空缺显示黑色
设置下 有中文(台湾)字样
设置-个性化-颜色菜单位置有误
视频模式的环绕声默认为近场,与预期结果不符
合入沙特国家需求
偶现铃声设置为空
一、实际常用工具
以下这些工具我会后续出其他文章进行详解
- ADB:安装设置APK、查询APK版本包名当前Activity等
- HierarchyViewer:对比Uiautomatorviewer,Hierarchy Viewer具有实时性、可视化优势
- Jadx 反编译工具:设置中会动态添加一些APK,例如定时关机、隐私、电量实验室等,部分情况需要验证资源
- MediatekDBViwer:用于分析SWT/ANR问题,可以查看CPU、低内存、IO等情况
- grep、find组合:无论是VSCode、Windows搜索都会有偏差、速度慢劣势,grep/find无疑是最常用手段
ADB常用命令
查看当前界面的app的包名
adb shell dumpsys window | findstr mCurrentFocus
查找apk对应的路径
adb shell pm path <包名>
导出apk
adb pull <apk路径> <导出位置>
查看apk包名版本
adb shell dumpsys package 包名 | findstr version
adb设置状态栏秒数(方便LOG)
adb shell settings put secure clock_seconds 1
adb查看SQLite数据库
sqlite3 <数据库文件名>(先通过shell进入到SQLite数据库所在的目录,通常是在/data/data/<包名>/databases/下)
adb安装APK
adb install apk路径
Jadx 反编译工具
jadx 是一款功能强大的反编译工具,可以反编译APK、反编译jar包,前者在实际中用途广泛 一般用于查看AndroidManifest、资源文件(字符串是否包含等) 打开jadx工具--文件--选择apk即可
grep、find搜索文件/代码
grep是根据文件的内容进行查找,会对文件的每一行按照给定的模式进行匹配查找
find是根据文件的属性进行查找,如文件名,文件大小,所有者,所属组,是否为空,访问时间,修改时间 所以通常我们将这两者结合使用
HierarchyViewer
1、本地安装SDK目录->sdk->tools->hierarchyviewer.bat(版本低,可能有未知bug)或点击同级目录的monitor.bat
2、Android Studio : 工具栏->Tools->Android->Android Device Monitor(官方推荐)
3、在命令行输入 hierarchyviewer(可用,但是启动的是版本低的)
MediatekDBViwer
DB常用文件说明
FileName | Info |
__exp_main.txt | 该文件包含程序运行中发生的异常汇总信息,通常用于调试和分析错误。 |
SYS_BINDER_INFO | 提供有关Binder IPC机制的信息,包括失败的事务、超时和成功的事务日志,有助于调试跨进程通信的问题。 |
SYS_CPU_INFO | 提供CPU的实时使用情况和性能指标,帮助开发人员监控和优化应用程序的CPU使用率。 |
SYS_FILE_SYSTEMS | 系统存储空间信息 (df) |
SYS_MEMORY_INFO/ DUMPSYS_MEMINFO SYS_PROCRANK | 系统memory使用信息 |
SYS_PROCESSES_AND_THREADS | 列出系统中当前运行的进程和线程的详细信息,帮助开发人员监控应用程序的运行状态 |
SYS_PROPERTIES | 系统属性信息 |
二、问题分析思路
问题分析思路
UI类问题
需求类问题
功能类问题
ANR问题
三、典型问题案例
从简单UI问题举例
固定拨号列表界面无法横屏
平板项目需要该界面横屏适配,在代码中判断平板进行更改属性值
public static final boolean xx_TABLET_TYPE="tablet".equals(SystemProperties.get("ro.product.type"));
public void onCreate(...){if(xx_TABLET_TYPE){setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_BEHIND); }else{setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); }
}
无障碍功能菜单,点击设置,底部空缺显示黑色
为主题设置属性
<item name="android:navigationBarColor">颜色</item>
设置下 有中文(台湾)字样
锁定逻辑代码,在遍历列表代码中替换字样
ArrayList<Pair<String,Locale>>entryPairs=new Arrary<Pari<String,Locale>>(availableLangs.size());for(int i=0;i<availableLangs.size();i++){Locale locale=mEnginesHelper.parseLocaleString(availableLangs.get(i));if(locale!=null){if(("中文(台湾)".equals(locale.getDisplayName())||("中文(台湾)".equals(locale.getDisplayName())){entryPairs.add(new Pair<String,Locale>("中国(繁体)",locale)); }//...正体 香港 }}
设置-个性化-颜色菜单位置有误
通过菜单名称检索资源文件、再去检索到了逻辑代码,是三方将包名进行了修改
protected boolean dynamicBindPreference(PreferenceScreen screen,Preference preference,Tile tile){//startif(TextUtils.equals("com.android.wallper/com.android.wallper.picker.CustomizationPickerActivity",tile.getDescription())){//endPreferenceCategory category=screen.findPreference("...xxx_category_key");if(category!=null){category.addPreference(preference); }else{screen.addPreference(preference); }return true; }return super.dynamicBindPreference(screen,preference,tile);
}
不支持电子说明书项目,用户反馈菜单应该在重置手机下方
通过其他相同问题,确定代码位置,添加国家代码
Settings/src/com/android/settings/SystemDashboardFargemnet.java
private int getVisiblePreferenceCount(PreferenceGroup group){int visibleCount=0;for(int i=0;i<group.getPreferenceCount();i++){final Preference preference =group.getPreference(i);if((KEY_MANUAL_GUIDE.equals(preference.getKey())||KEY_MANUAL_GUIDE_CATEGORYequals(preference.getKey())...)){preference.setVisible(false); }if(!DevelopmentSettingsEnabler.isDevelopmentSettingsEnable(requireActivity())&&"developer_mode_category".equals(preference.getKey())){preference.setVisible(false);continue; }if(preference instanceof PreferenceGroup){visibleCount+=getVisivlePreferenceCount((PreferenceGroup)preference); }else if (preference.isVisible()){visibleCount++; } }return visibleCount;
}
视频模式的环绕声默认为近场,与预期结果不符
初次进入DTS,或重置DTS模式时,并非为进场,与预期不符
判断该BUG为功能类BUG,由于观察到本项目有正确的默认值,所以判断和逻辑代码有关(判断进行设置值),于是我们进行BUG检索发现xxxx有类似的BUG,我们观察修改链接可以看到DTS的相关源代码(本项目没有该源码)
public class DtsDefualtSettings{private boolean mDoubleSpeaker;private boolean isDoubleSpeaker(){mDoubleSpeaker="1".equals(Settings.Global.getString(mContext.getContentResolver(),"xxx_dual_mic_support"));Utils.logd(TAG,"isDoubleSpeaker="+mDoubleSpeaker);return mDoubleSpeaker; }
}//可以看到通过Settings.Global xxx_dual_mic_support来判断是否为双声道项目
//检索framework发现并没有定义xxx_dual_mic_support对应的属性
/base/servuces/core/java/com/android/server/audio/AudioService
private static final boolean XXX_DUAL_MIC_SUPPORT="1".equals(SystemProperties.get("ro.vendor.xxx_dual_mic_support","false"));
if(XXX_DUAL_MIC_SUPPORT){Settings.Global.putString(mContext.getContentResolver(),"xxx_dual_mic_support",1);
}else{Settings.Global.putString(mContext.getContentResolver(),"xxx_dual_mic_support",0);
}
所以解决办法就是添加宏控 vice/xxx/product_parts/device_sdd.mk
ifeq($(strip$(XXX_DUAL_MIC_SUPPORT)),yes)PRODUCT_PRODUCT_PROPERTIES+=ro.vendor.xxx_dual_mic_support=1
endifdevice/xxx/product/xxxxxxx/ProductConfig_SDD.mkXXX_DUAL_MIC_SUPPORT = yes
合入沙特国家需求
简单来说:需要在设置中显示认证信息菜单以及提供的认证号 所以可以知道 这类菜单一定是有相关判断逻辑与开关,也有相关位置存放认证号,从BUG详情中我们看到了认证号
根据我们的设置问题分析步骤,仅从标题就可判断此BUG为需求类BUG,所以其他项目大概率是有该需求。于是我们查询上一项目:其他项目找到了类似的问题可以提供思路。(后续发现修改并不完全一致)例如:从其他项目我们大致确定了该界面的逻辑代码位置 Settings/src_xxx/com/xxxxxx/aboutphone/CertigiedInfoActivity.java 让我们看看关键代码
String model=getShortModel();//获取品牌名称(截取后的)例如xxxx
mCkView=(LinearLayout)findViewById(R.id.xxxx_ckd_ll);
boolean isBrazil=TsUtils.equals(TsUtils.getCountryCode,CertigiedInfoPreferenceController.COUNTRY_CODE_BR);
//CertigiedInfoPreferenceController也是涉及到的一个类
boolean isSupportDoc =CertifiedInfoActivity.isSupportDoc(mResources,model);
mDocView.setVisibility((!isSupportDoc||FeatureOption.XXX_DOC_NOT_SUPPORT||isBrazil)?View.GONE:VIEW.VISIBLE);
boolean isCitcSupport=isSupportCitc(mResources,model);//检索品牌名称是否在资源文件中,接下来我们看一下isSupportCitc方法,便可以知道需要认证的项目存放在哪个资源文件
boolean isSa=TsUtils.equals(TsUtils.getCountryCode(),CertigiedInfoPreferenceController.COUNTRY_CODE_SA);
mCitcView.setVisibility(isCitcSupport&&isSa?View.VISIBLE:View.GONE);
public static boolean isSupportCitc(Resource res,String model){if(TextUtils.isEmpty(model)){reutrn false; }model=model.getLowerCase();List<String> citcProjectsList=null;try{citcProjectsList=Arrays.asList(res.getStringArray(res.getIdentifier("xxx_citc_projects_support","array",mCertifiedResPkg)));//我们看到了获取xxx_citc_projects_support列表}catch(NotFoundException e ){return false; }if(citcProjectList==null||!citcpRojectsList.contains(model)){return false; }return ture;
}
所以,我们确定了资源文件以及资源id:xxx_citc_projects_support,
可以直接进行命令搜索该资源文件,并添加项目名称 为了确保万无一失,使用adb查找ro.product.model属性确定名称
<string-array name="xxx_citc_projects_support" translatable="false">
<item>项目名</item> ... <item>项目名</item>
</string-array> 并添加认证号 t0_sys/device/xxx/product/xxx/ProductConfig/vendor/prjconfig/overlay/vendor/xxx.../app/XXXSettingsApk/res_app/values/certified_strings.xml
设置认证码,此处为overlay Setting 如果只是在原生(客制化)Setting中设置认证码会被这里覆盖
<string name="xxx_citc_sign">"(TA xxxxxxx)"</string>
偶现铃声设置为空
现象:手机格式化\重置,到设置-声音与振动中观察,期望结果是默认铃声为A、通知提示音为B,但是偶现默认铃声与通知提示音都为无
此问题涉及公司机密,相关信息与代码脱敏后另写一篇