📮 遇到问题请把诊断报告发我
报告能看出"你自己看不到"的问题 —— 比如某个字体其实一直没挂上、
或者被别的模块挡掉了,界面上一切正常,只有报告里能查出来。
这一版的修复,基本都是从大家发来的报告里找到的。
一、修好了中文字体挂不上
现象
· 显示"已生效 170/172",差的恰好是中文
· 每次「免重启应用」都报:
mount: '.../xxxxx.ttc5_2-3' -> '/system/fonts/NotoSansCJK-Regular.ttc':
No such file or directory
· 中文一直是系统默认字形,其它文字都换了
原因
那个 .ttc5_2-3 是中文字体的"合集包装产物":系统的中文字体是一份 5 个 face
的合集(简/繁/日/韩/港共用),模块要把你的字体塞进对应那几号 face。
毛病出在换字体 / 重装之后:
① 上次「应用」生成产物 A,挂到 /system/fonts/NotoSansCJK-Regular.ttc ← 成功
② 之后又「应用」:产物 A 被清掉(新计划指向产物 B)
★ 但【挂载还在】—— 挂载钉的是文件本体,文件名消失不影响已挂上的
Linux 就把这层挂载标成"已删除"(mountinfo 里带 //deleted)
③ 现在要把 B 挂到同一位置:
那位置【已经有挂载了】,系统不覆盖它,
而是去找"那层挂载里面"的路径 → 找不到 → 报"文件不存在"
★ 报错完全指错方向:两个文件都好好地在硬盘上
怎么修的
挂载前先扫挂载表,把"指向已删除文件"的旧挂载卸掉再挂新的:
清掉 2 个「指向已删除文件」的旧挂载(否则新文件挂不上去)
新挂上 2 个
实际生效:172/172
顺带修的三个隐患
- 产物被误删:清理逻辑遇到"计划文件为空/损坏"会把正在用的产物也删掉。
现在改成宁可不清理,也不删正在用的。 - 免重启后数字不对:界面的"实际挂载/实际生效"读的是开机时的快照,
而免重启不改开机标识 → 快照一直"有效"→ 数字永远停在开机那一刻。
现在挂载完就按当前真实情况重算。
另外还修了一个由此引出的显示问题:重算时记"这是哪次开机写的"用的那个函数
只存在于另一个脚本里,独立运行时取到空值 → 界面认不出记录
→ 显示成"本次开机未挂载"(而"实际生效"是满的,自相矛盾)。现在自带一份。 - 合集生成失败不留线索:以前失败静默跳过(报错被丢掉),报告里查不出原因。
现在把失败原因、产物大小、剩余空间写进ttc.log,报告里直接能看到。
二、适配临时 root —— 不用重启,字体也能生效
临时 root(KernelSU late-load 这类)的困境:重启后 root 掉了,开机脚本没机会执行,
字体一个槽位都换不上 —— 不是模块坏了,是它没被叫起来干活。
界面底部「让字体生效」给两条路:
| 免重启应用 | 重启手机 | |
|---|---|---|
| 要多久 | 点一下,屏幕黑一下,30~60 秒 | 一次重启 |
| 临时 root | 必须走这条 | 重启后 root 会掉,白重启 |
| 普通 root | 也能用,省一次重启 | 最稳 |
它做两件事:① 把字体挂进 init 的挂载命名空间(必须走 nsenter,
否则 root 命令的挂载 system_server 看不见 → "显示成功、字体没变");
② 让系统界面重新读一次字体(软重启 zygote)。
踩过的坑:符号链接槽位要先解析真实路径;按 inode 判断是否已挂好
(不按文件大小,大小相同的不同字体很常见);软重启后状态自动跟上
(以前只有开机流程才更新"当前生效",软重启不跑它 → 界面显示旧字体)。
它不改变开机行为 —— 以后每次开机模块还是照常自己挂载。挂载不写系统分区,
出问题长按电源键重启就干净了。
三、一键上报改成传到我自己的服务器
以前发邮件,正文有长度上限,而"哪些字体没进计划"那段在 AOSP 上能列出几百个
小语种字体名 —— 正文被服务端砍掉,砍掉的恰好是最该看的几段。
现在传自己的服务器,单份上限 8MB。
① 一键上报 → 两秒生成、点一下传上去,你会看到一个编号
② 连接自检 → 传不上去时点它:分三段告诉你卡在哪
③ 导出小报告 → 存到 Download/快捷报告.txt
⚠️ 上传前请先连 VPN(服务器在国外)。连不上就点「连接自检」。
顺手修的:界面上传走的是 WebView 的网络请求,而KernelSU 的 WebView 不走梯子代理
(手机浏览器能打开、界面却说 Failed to fetch)。现在改成借 shell 里的 curl 出网。
四、诊断报告:不再刷屏、也不再误报
- 不再被无关字体名占满:只列"看着该换却没换"的,其余压成一行统计。
以前 AOSP 上几百个小语种字体全列出来,把有用的信息挤没了。 - 不再把装饰字体误报成「★要修」:
ComingSoon.ttf/DancingScript-Regular.ttf
族名就是casual/cursive,不换是刻意设计。 - 不再对
/data/fonts下绝对结论:以前一节说"会盖过 /system/fonts"、
另一节说"本报告不替你下结论",自相矛盾。现在用本次计划对照,点名列出是哪几个。 - 装了 mountify 的机器能查到配置了(以前只找 Hybrid Mount 的路径)。
- 「App 里字体没变」直接给"一次搞定"的办法:报告会实测出"管理器把模块从
应用进程里卸载了",然后告诉你在/data/adb/ksu/.feature_config加
kernel_umount=0,一次对所有 App 生效。
五、小米硬件刷类原生 ROM 不再被认成「澎湃OS」
ro.product.brand 是硬件品牌(刷什么 ROM 都报 xiaomi),ro.miui.* 属性又会残留,
于是类原生机器被认成了 HyperOS。
现在多要一个实证:设备上得真有小米专有字体(MiSans* / MiLanPro* / MiHaus*)。
真机对照很干净 —— 真 HyperOS 有 51~60 个,类原生上 0 个。
六、界面:几处调整
- 报告入口挪到中部、只留一处(「自带挂载」和「谷歌字体兼容」之间),
以前主界面一个按钮 + 弹层里一个,容易懵。 - 弹层底部按钮不再被截字:最多 5 个按钮挤一行时,窄屏上文字被切掉一半。
现在按文字宽度定尺寸,放不下就整行折下去。 - 两处"要挂梯子"的提示:模块更新下面、上报弹层里。
- 「无法读取」不再误报:以前刷新过程中任何一步出错,就把「当前实际生效」
「识别系统」覆盖成"无法读取",哪怕槽位数据明明读到了。现在只有真的
跟模块说不上话才报。 - 刷入日志不再"读不通":长行在手机上被硬折在词中间,现在在自然断点拆开。
七、点更新报「更新失败」,其实装成功了
界面派发后台安装任务后立刻去问"现在什么阶段",而那一刻后台还没写出状态 ——
界面把"没有状态"当成了"已经结束",于是报失败、恢复按钮。但后台其实还在跑,
最后真的装成功了。
现在"还没开始"和"已经结束"区分开了,进度条全程跟着走(下载 097%、安装 97100%),
装完按钮保持「立即重启生效」。
八、其它
- 快捷报告加了字节上限兜底,超了会明确写"已在此截断"。
- 免重启脚本的挂载命令用绝对路径(
timeout起子进程时 PATH 受限)。 - 报告里"运行位置"显示完整路径,不再显示成
.。