Android 字体引起的简单问题

本文分析了一款非原生Android手机在更改字体设置后,关机界面与crash弹窗仍显示默认字体的问题。通过逐步排查,最终定位到SELinux权限配置导致字体文件无法被zygote进程正确读取的原因。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题:

手机更改设置完字体后,关机界面与crash 弹窗,仍是默认字体,launcher 、systemui、apk 却正常。


手机更改默认字体的 方案为(非原生):

在 android.graphics.Typeface类的create方法中,进行判断,如果设置了字体那么就返回 设置的字体(REPLACE_TYPEFACE),如果没有设置字体那么就返回默认字体。

设置字体,会调用Typeface 类的updateTypeface方法将,设置的字体给赋值给REPLACE_TYPEFACE。


进行尝试:

手机设置字体, 关机界面与crash 字体改变没有问题。

重启手机,关机界面与crash 字体恢复默认字体发生问题,(测试没有描述清楚,之前做了好多测试,排除好多疑点,才发现浮现步骤)


分析:

未关机,字体没有问题,一旦关机system_server就发生问题,

system_server 与 其他进程都是从zygote 中fork 出来的。如果有问题应该统一有问题,

在Typeface 中REPLACE_TYPEFACE使用和可以设置发生改变的地方添加log(即 create 与updateTypeface 方法中)

发现:

system_server 中 REPLACE_TYPEFACE 为 null

apk、launcher、systemui,在启动时会在ActivityThread.java 中调用updateTypeface 方法,去重新设置字体。

由此怀疑,在zygote启动时,最初REPLACE_TYPEFACE就没有设置进去,

后来其他进程更新设置字体,所有没有问题,

而system_server ,没有更新设置字体,所以有问题。



查看开机时 REPLACE_TYPEFACE 的初始化赋值:

判断 /data/fonts/font.ttf 文件是否存在,如果存在,使用 设置的字体(即font.ttf), 如果不存在 使用默认字体。

File fontFile = new File("/data/fonts/font.ttf");

if(fonFile.exists()){

********

}

********

字体文件明明存在,这段代码,却判断不存在,怀疑是权限问题,修改代码:

File fontFile = new File("/data/fonts/font.ttf");

File fontDir = new File("/data/fonts");

Log.d(TAG, "fontDir canRead: " + fontDir.canRead() + ", canExecute:" + fontDir.canExecute() + ",  fontFile  canRead" + ****);

if(fonFile.exists()){

********

}

********

测试结果发现, /data/fonts 不可读,不可执行, 所以判断文件不存在,

进入手机中查看文件夹权限却为 777 ,没有问题。


那之后可能和selinux 有关了,获取开机时的 kernel log 发现:

for pid=646 comm="main" name="fonts" dev="dm-1" ino=917505 scontext=u:r:zygote:s0 tcontext=u:object_r:fastplay_data_file:s0 tclass=dir permissive

由此知道了开机时,selinux 限制了  zygote 读取 fonts 文件夹,所以zygote 使用的是默认字体,

system_server 与其他进程从zygote fork出来也是使用的默认字体,但其他进程会在ActivityThread 中进行再次加载更新,所以没有,

而system_server 没有此步骤,所以发生问题。


为啥M版本没有问题:

在 M 版本上没有问题是因为,
字体文件&文件夹( /data/fonts/fonts.ttf ) ,
是在apk:com.***.android.theme 中创建的,此apk 为system_app 拥有读写、创建system_data_file 的selinux 权限
//文件external/sepolicy/system_app.te
auditallow system_app system_data_file:dir
{ create setattr add_name remove_name rmdir rename }
;
auditallow system_app system_data_file:file
{ create setattr append write link unlink rename }
;
所以在M 上 字体的相关文件夹与域为 system_data_file , zygote 有用读写的selinux 权限没有问题。
在N版本上(external/sepolicy 文件夹消失)
system_app 没有配置system_data_file 的selinux 权限 ,而配置的是fastplay_data_file 的域 ,以此创建的 字体相关 文件,
而zygote 没有权限读取 此类域文件,所以发生问题。


测试 没有描述清楚问题,

没有及时从system_server、apk 进程联想到zygote 的问题,

找到问题,怀疑是底层问题,没有看kernel log

这些造成耗费了大量时间。




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值