Repository navigation
Releases: ACLaniakea/coloros-pad-fixes
Release list
ColorOS Pad Fixes v4.1.3
4.1.3
本版只修正刷新率策略,不改变面板能力、内核或内存参数。
刷新率
移植 ROM 的 refresh_rate_config.xml 缺少 144Hz mode 声明时,用户手动选择最高
刷新率会让 rateId=4 落入错误降级路径。模块继续补齐
8750R60_90_120_144,但不再以此覆盖系统策略:
- 默认自动档恢复为 120Hz;
- 所有应用配置的自动字段
rateId[0]由 144Hz 改为未指定,交还框架; - 手动最高档的
rateId[3]=4保留,因此只在用户手动选择最高档时请求 144Hz; - 手写笔实际书写时仍通过原厂
OplusRefreshRatePolicyImpl的
settings_enable_oppo_pencil投票使用 120Hz; - PenBridge 不再读取或写入用户的
min_refresh_rate、peak_refresh_rate。
完整重启后,在显示设置中选择自动、60Hz、最高三个档位验证;自动档不应因桌面或普通
应用被强制为 144Hz,最高档应可正常启用 144Hz。
内存观察
本轮运行态检查未发现相机预填池泄漏。池已回填至 192MiB,预填线程空闲。当前系统
压力主要来自活跃工作集和图形映射;本版不以未经 A/B 的方式调整相机池容量或 swap
参数。
4.1.2
4.1.2
Warning
仍须成对刷入 boot-ACLaniakea-SM8650Q-droidspaces-r3.img 与
vendor_boot-hyperSched-stub.img。本版 BSP 依赖 r3 导出的符号;不要与 r2 或实验
内核混用。
本版针对 TB710FU 运行 OPD2513 时的长待机亮屏内存峰值。所有项目自有的 KernelSU
模块与 LSPosed APK 统一重建为 4.1.2 / 410002。
修复
- 新增
oplus_boost_pool:以 qcom system heap 的分配与释放调用点接入原厂同形态的
预填池、shrinker 与补水线程。平板默认预留 192 MiB(64 MiB SurfaceFlinger、128 MiB
camera);不照搬 PKX110 的 564 MiB,以免在 7.8 GiB 设备上制造新的常驻压力。 - 相机池仅允许已绑定的 camera provider 消费 camera reserve;空闲哨兵为原厂语义的
camera_pid=1,普通 qcom-system 客户端不能耗尽相机预留。 - 启动期设置
debug.oplus.adaptive.preview=false,避免电话紧凑窗口框架把平板留在
VFX parallel-world 合成状态,进而保留大块全屏客户端合成缓冲。 - 撤销曾写入
vendor.display.gpu_rendering=false的覆盖。该覆盖会破坏显示启动链,曾与
软重启及 KernelSU 状态异常同时出现。 - SurfaceFlinger 只在开机后一次性从
/foreground迁移至原厂对应的/sfcpuset;不
重启 SurfaceFlinger,不新增轮询或守护脚本。 - 全局和根 memcg 的 swappiness 与 PKX110 当前 ColorOS 基线统一为 125;apps 子组仍由
Athena/OSense 自主管理。
验证
相机池实机验证:分配与释放 kprobe 均命中一次;camera provider 会话期间
camera_pid 从 1 转为 provider PID,池页可被消耗并回填。熄屏 9 分钟后亮屏 3 秒内
观测到 allocstall +1、pgsteal_direct +63、pgscan_direct +64,且无新增内核告警。
完整排查数据见
4.1.1 卡顿与内存回收排查 第 19.5 节。
已知限制
长待机后的亮屏路径还会创建 SystemUI、Launcher、ColorFade 与 Taskbar 的不可换出图形
共享缓冲,无法由相机池替代。该版本降低相机 HAL 的同步直接回收,不保证消除所有桌面
或锁屏动画掉帧;后续应以真实人脸解锁的池峰值与帧时间继续 A/B。
4.1.1 — 修好待机后动画卡顿与前摄指示灯,配套 r3 内核
Warning
配套内核改为 r3,必须成对刷入 boot-ACLaniakea-SM8650Q-droidspaces-r3.img 与 vendor_boot-hyperSched-stub.img。
本版 OPlus BSP 模块依赖 r3 才导出的 filp_open,在 r2 上会加载失败。
vendor_boot-ColorOS16-original-TB710FU.img 仅用于回退原始 ColorOS 引导链,不能与本项目的 boot 混刷。
adb reboot bootloader
fastboot flash boot boot-ACLaniakea-SM8650Q-droidspaces-r3.img
fastboot flash vendor_boot vendor_boot-hyperSched-stub.img
fastboot reboot修好待机后动画卡顿与前摄指示灯失效,重新接回 KGSL 显存回收链(按对照机
PKX110 的行为重做策略),把 HybridSwap 的 swapd_pause、swappiness 与 THP 三项
交还 ColorOS 原厂语义,并清零模块加载期与运行期的内核告警。
完整的定位过程与实测数据见
4.1.1 卡顿与内存回收排查,
尤其是第 14、17、18 节。
主要修复
KGSL 显存回收链接回,并且不再拿解锁动画买单
4.1.0 以"原厂不驱动、待机收益无人消费"移除了 KGSL state 桥。两机同负载对照推翻了
这两条理由:对照机的 Unevictable 在 30 次应用启动里恒为 69MB,平板是
1.0~1.6GB——联想这版 msm_kgsl 把显存 1:1 钉成不可回收,只能靠把进程标成
background 解钉;移植包缺了写这个节点的组件。对照机不需要,是因为它根本不钉。
消费者也不是"待机",而是前台负载本身:平板 allocstall 约 8001000 次/秒,对照机114 次/秒。
20
开发中的 v4.1.1 桥改成 shrinker 驱动,但它的 oom_score_adj tracepoint 在 adj 变到
=100 时就立即写
background,与压力无关。熄屏后桌面被锁屏遮住、adj=100,
20 秒内 114MB 显存被整体回收,解锁时从 zram 读回——这正是待机后动画卡顿。
出货的 v4.1.2 桥按对照机的行为定规则:
| 对象 | 何时标 background | 何时还原 |
|---|---|---|
| adj < 0(SF / system_server / SystemUI) | 永不 | — |
| 缓存进程 adj >= 900 | 内存压力扫描 | adj 落回 900 以下 |
| UI 带 100 <= adj < 900 | 压力扫描,且亮屏、亮屏 30s 后、连续遮挡 >= 60s、显存 >= 192MB | 熄屏立即还原;adj 变化时还原 |
壁纸、com.oplus.blur、输入法、侧边栏永远不碰;shrinker 回调里不做文件 I/O。
运行时参数在 /sys/module/oplus_kgsl_state_bridge/parameters/,说明见
kernel-compat/kgsl_state_bridge/README.md。
实机:熄屏 60 秒,压力扫描标记 15 个缓存进程,桌面(742MB)、壁纸、blur、SystemUI
gpumem_reclaimed 全为 0。
前摄指示灯失效:LSPosed 被钉回旧 Hook
机器上装有两份同 id 的 FixModule(正式安装 + 开发推送),两份都在 zygote 前把
LSPosed 模块路径钉到自己目录下的 APK,谁晚谁赢。开发推送带的是一份停在
2026-09-02 的 Hook,system_server 于是跑着 3.2 时代的钩子:没有前摄灯事件桥,
09-13 已撤回的"缓存进程上限 48"也回来了。
hook/versionCode改由 Hook manifest 生成(此前从 3.0 起一直是 301115,
开机时的升级检查因此从未生效);- 路径同步工具发现当前钉住的是另一份仍启用、且版本不低于自己的模块副本时,
拒绝改写并在日志里提示删除重复目录。
升级前请确认
/data/adb/modules/下没有两个同为coloros_port_fix或
aclaniakea_oplus_bsp的目录。
HybridSwap 与内存策略交还原厂
| 项 | 改动 | 依据 |
|---|---|---|
swapd_pause |
删除面板桥接管后永久清零的覆盖,恢复原厂 setter | 对照机:亮屏约 1.2s 后置 1、压住约 6s 放开;swapd_manual_pause 恒 0 -> 70s 内 +189,331 |
| zram_opt swappiness | 160/200 -> 125/125 | 对照机的编译期默认值 |
| THP | always -> never |
联想 vendor 启动脚本写 always,OPlus 写 never;thp_fault_fallback 406,637 -> 0 |
这三项在压力基准里都没有可测的性能收益,是保真修复,不是性能修复。
内核告警清零
oplus_cpu_sched_sched_info:hot_thread_node缓存带构造函数又用 zalloc 分配,
触发mm/slub.c:2013告警,去掉构造函数。- 11 条
proc_dir_entry ... already registered:多个一加模块各自创建
/proc/oplus_mem、/proc/task_info,撞名即告警。改为先探测目录再创建;
节点位置与改动前逐项一致。 - 仅剩联想原厂
cps_wls_charger的一条 vendor 告警。
配套内核 r3
boot-ACLaniakea-SM8650Q-droidspaces-r3.img,需与 vendor_boot-hyperSched-stub.img
成对刷入。
6.1.128-android14-11-sm8650q-droidspaces-r3- 相对 r2 只多两个白名单导出:
filp_open、kernel_write(KGSL 桥与 proc 目录探测使用) module_layoutCRC 仍为0xea759d7f;289 个 Lenovo/QTI vendor 模块 CRC mismatch 为 0
验证
安装并重启后:
adb shell uname -r # 6.1.128-android14-11-sm8650q-droidspaces-r3
adb shell su -c 'grep -c . /proc/modules' # 490
adb shell su -c 'cat /sys/module/oplus_kgsl_state_bridge/parameters/stat_failed' # 0
adb shell su -c 'cat /sys/module/oplus_bsp_zram_opt/parameters/vm_swappiness' # 125
adb shell su -c 'cat /sys/kernel/mm/transparent_hugepage/enabled' # [never]
adb shell su -c 'dmesg | grep -c "already registered"' # 0打开前置相机,物理指示灯应亮起,关闭后熄灭。
已知限制
- 解锁窗口的 p95 帧时尚未与 4.1.0 做正式对照。
- 亮屏重度使用后桌面若被 UI 带标记,回到桌面时可能有一次钉回的顿挫;明显时可调大
ui_min_mapped_mb或设ui_band_enabled=N。
其余模块
随统一版本号重建,内容未变。
4.1.0 — 修好从未闭合的熄屏闸门,配套 r2 内核
Warning
必须成对刷入 boot-ACLaniakea-SM8650Q-droidspaces-r2.img 与 vendor_boot-hyperSched-stub.img。
vendor_boot-ColorOS16-original-TB710FU.img 仅用于回退原始 ColorOS 引导链,不能与本项目的 boot 混刷。
adb reboot bootloader
fastboot flash boot boot-ACLaniakea-SM8650Q-droidspaces-r2.img
fastboot flash vendor_boot vendor_boot-hyperSched-stub.img
fastboot reboot修好 HybridSwap 那条从未闭合过的熄屏闸门,补上从未挂载的 /dev/mqueue,
并修正一处会让新增文件被静默漏发的打包缺陷。
本版开发过程中还调查了 KGSL 显存回收链并做出过一个内核桥,最终判定不该出货
并已移除,原委见下。
完整的定位过程与实测数据见
r3 内核与 KGSL 桥验证。
主要修复
熄屏闸门从未闭合,以及它连带废掉的 HAL 控制
HybridSwap 的面板 kprobe 挂在 panel_event_notification_trigger 上,按
notif_type 1/2 读 blank/unblank。实测该函数在本机只送 notif_type=4
(FPS 变化,负载 144/120,正是这块 144Hz 屏的刷新率)。两路屏幕信号同时失效:
display_off从初值 0 起永远不变 —— 熄屏时该停的主动回收从未停过
(wakeup_swapd与swapd_shrink_node都靠它提前返回);hybridswapd_panel_bridge_active()只看 kprobe 注册标志,而注册确实成功,
于是swapd_pause_store无条件清零并丢弃厂商 performance HAL 的写入。
对照机 PKX110 的swapd_manual_pause是 2.27 亿次,平板修复前恒为 0。
改挂 msm_drm 的 dsi_panel_power_off / dsi_panel_power_on,并要求桥真的观测到
过一次转换才接管。冷启动后实测:亮屏 20 秒 over_min_skip +83,780,熄屏 20 秒
+3(停转),唤醒后 +4,328(恢复)。
教训:判定一个探针"可用"要看它有没有真的收到过事件,不能只看注册返回值。
/dev/mqueue 从未挂载
内核开了 CONFIG_POSIX_MQUEUE,但 Android 的 init 不挂 mqueue。
4.0.4 加的挂载逻辑用了 grep -q '\bmqueue\b' 做能力检测——toybox 的 grep
不支持 \b,匹配恒空,于是每次开机都记下"内核不支持,跳过",挂载从未执行。
改用 -w 整词匹配。至此 DroidSpaces 所需的内核能力齐全。
BSP 打包脚本会静默漏掉新增文件
build_oplus_bsp.py 用的是写死的文件白名单,当时新增的 sepolicy.rule 就这么被
漏掉了——而那条规则是它要配套的功能的前提,少了它整个功能等于没做,却毫无迹象。
改为模块根目录下的普通文件一律随包出货。
(那个 sepolicy.rule 后来随 KGSL 桥一并删除,但打包脚本的缺陷是通用的,修正保留。)
清掉不再需要的早期改动
- 删
fix-module/module/bin/kgsl-state-sync.sh(6 秒轮询的用户态同步器)及
service.sh/uninstall.sh里配套的清理段。那段在每次开机时无条件把所有
background进程写回foreground,遍历全部 KGSL 节点——纯粹的开机开销,
而它要兜底的那个轮询器早已不随模块出货。 - 删
kernel-compat/oplus_hybridswap_panel_bridge/与其构建脚本:它挂的是同一个
只送 FPS 事件的函数,从来没起过作用。 - KGSL state 桥本身也已移除,见上。
KGSL 显存回收链:调查结论是不做
平板的 Unevictable 与 KGSL page_alloc 是 1:1(677MB 对 679MB),对照机
PKX110 是 719MB 对 71MB。追下去发现联想的 msm_kgsl 里有一整套 process
reclaim,但链条第一环是断的:
没人写 /sys/class/kgsl/kgsl/proc/<tgid>/state
-> 进程恒在 PINNED 态
-> kgsl_reclaim_shrink_count_objects() 恒返回 0
-> 内核永远不调用 scan_objects
-> 显存永久不可回收
kprobe 实测:3GB 压力下 count_objects 被 do_shrink_slab 调用 1328 次、
次次返回 0,scan_objects 命中 0 次。手工写一次 background,count 立刻
返回 0xc800,12 秒内吐出 150MB。机制本身完好。
据此做了一个内核桥补上写入者,熄屏实测释放 450~510MB。但随后两项证据推翻了它:
- 原厂不用这套。 逐个扫过 ROM 里所有引用
kgsl/kgsl/proc的组件
(libAlgoProcess.so、memtrack-service、autochmod.sh、若干 sepolicy),
全是只读统计,没有任何一个写state;参照机命中同一批组件、同样只读,
而且它的proc/<pid>/下连state节点都没有。 - 收益兑现不了,代价正好落在用户抱怨的交互上。 待机腾出的内存没有消费者,
而这笔钱要在下一次解锁时连本带利还:解锁窗口桌面的 95 分位帧时,熄屏回收过
的两轮是 101ms / 121ms,没回收的那轮只有 24ms。桌面是唯一的显存大户,
也是解锁时第一个重画的东西——对照机在解锁时桌面一帧都不重画。
而且平板实测 内核击杀记录为 0、PSIsome avg10=0.30、可用内存约 2GB,
它根本不缺内存,连"防 OOM"的理由也不成立。
一个原厂不用、参照机也不用、收益无处兑现的机制,不该留在出货包里。桥已移除,
源码与验证记录留在仓库作为已排除路径。本版不改变 KGSL 的行为。
配套内核 r2
boot-ACLaniakea-SM8650Q-droidspaces-r2.img,需与
vendor_boot-hyperSched-stub.img 成对刷入。
6.1.128-android14-11-sm8650q-droidspaces-r2- SysV IPC 走
ANDROID_KABI_RESERVE预留槽,module_layoutCRC 保持
0xea759d7f;289 个 Lenovo/QTI vendor 模块静态检查 CRC mismatch 为 0 - Gloom / pcppages hook、32KB module percpu 预留
- 原厂
TRIM_UNUSED_KSYMS与 BTF 配置不变
为什么不是 r3
本版开发过程中曾短暂用过 r3。r3 相对 r2 的配置差异只有一行
CONFIG_LOCALVERSION,唯一的实质改动是把 filp_open、kernel_write 加进
符号白名单——那纯粹是为 KGSL state 桥加的。桥既已移除(原因见下),这两个导出
就没有任何消费者,r3 相对 r2 不再提供任何东西,因此退回 r2。
本版的其余修复(HybridSwap 熄屏闸门、/dev/mqueue 挂载)都在模块里而不在
内核里,r2 上照常工作——已实机确认:内核 kprobe 注册表里有
dsi_panel_power_off / dsi_panel_power_on(均由 hybridswap 模块注册,标注
msm_drm),一次熄屏/亮屏各触发一次;490 个模块全部加载,0 熔断。
一条需要更正的历史结论
4.0.4 发布说明称"改为内核 kprobe 接 Lenovo 面板真实 blank/unblank 事件,
恢复 display_off 闸门"。本轮实测表明这个结论不成立:
panel_event_notification_trigger 在本机只送 FPS 变化事件
(notif_type=4,负载 144/120,正是这块 144Hz 屏的刷新率),从不送
blank/unblank。旁证是 swapd_manual_pause 在平板上恒为 0,而对照机
PKX110 是 2 亿次——手机在亮屏时暂停 swapd,平板从未暂停过。
本版的 KGSL 桥改挂 msm_drm 的 dsi_panel_power_off / dsi_panel_power_on,
实测每次屏幕转换各触发一次、无歧义。HybridSwap 那条熄屏闸门也已在本版一并
修好,见上面"熄屏闸门从未闭合"一节。
验证
安装并重启后:
# DroidSpaces 能力齐全
adb shell su -c 'grep -c " /dev/mqueue " /proc/mounts' # 1
adb shell su -c 'ls /proc/sysvipc/' # msg sem shm
adb shell uname -r # 6.1.128-android14-11-sm8650q-droidspaces-r2490 个模块应全部加载、0 熔断;dmesg 无 panic、无 avc 拒绝。
其余模块
随统一版本号重建,内容未变。
4.0.4 - 接回被移植弄断的 AOT 与内存链路
4.0.4
把移植过程中被弄断的 AOT 与内存链路接回原厂形态。改动集中在
OplusBSP-Modules 与 FixModule 两个包,其余模块随统一版本号重建、内容未变。
完整的定位过程、实测数据与被排除的假设见
4.0.4 内存与 AOT 排查记录。
修复
| 项 | 说明 |
|---|---|
| system_server 里 ColorOS 那半边一直在解释执行 | oplus-services.jar 与 oplus-service-jobscheduler.jar 的镜像内 odex 是移植者用裸 dex2oat 编的(无 --class-loader-context),ART 收 vdex 拒 odex。修复脚本改为遍历整条 SYSTEMSERVERCLASSPATH,并修掉三个会产出废品的 bug |
补回缺失的 oplus_mm_proactive_compact |
它的目录没有 Makefile,构建脚本因此漏掉。补上后 /proc/oplus_mem/fragmentation_index 出现,原厂主动规整链路重新闭合 |
| osvelte 节点命名与 lmkd 重挂 | 构建时 CONFIG 并集打开了 _DBG,procfs 根与字符设备变成 osvelte_dbg。改回 osvelte 后 /dev/osvelte 的属主权限标签与对照机一致,并桥接 lmkd 重新持有它 |
| hybridswap 熄屏不停工 | display_off 依赖的面板通知器因平台 CONFIG 未定义而被编掉,永远为 0。加熄屏桥后 hybridswapd 由 31.1% 降至 0.0% 单核 |
| 撤销我们自己对 swappiness 的覆盖 | 此前一律写 vm=125 / swapd=125,理由只是对齐对照机。本机原厂是 vm=160,swapd 专用档模块默认是 200。现已交还原厂 |
| 撤销我们自己对缓存进程上限的降档 | 我们的 BaseFix hook 一直把 AMS 缓存进程上限从原厂的 96 压到 48,是后台留存明显差于对照机的直接原因。当初压低的实测依据成立,但取自本版四项修复之前。现改为默认不干预,persist.sys.aclaniakea.max_cached(8~256)可按需重新降档 |
| AOT 产物加构建指纹 | 包内自带产物绑死本套 ROM。绑定前逐项校验指纹,不符就跳过并由脚本重编,装到别的移植包上不会覆盖人家原厂的产物 |
验证
安装后重启,逐项应为:
oplus_bsp: 34 loaded, 0 failed
services / oplus-services / oplus-service-jobscheduler odex段 全 = 3
swappiness: vm=160 direct=60 swapd=200 kswapd=160
/proc/oplus_mem/fragmentation_index 存在
CUR_MAX_CACHED_PROCESSES = 96(原厂值,由 Athena 按本机产品配置算出)
/proc/osvelte 下有 8 项,/dev/osvelte 为 system:system u:object_r:osvelte_device:s0
日志 swapd-screenoff: 桥已启动
对应命令:
grep -a 'oplus_bsp:' /data/adb/oplus_bsp.log | tail -1
for b in services oplus-services oplus-service-jobscheduler; do
echo "$b $(grep -c "oat/arm64/$b\.odex" /proc/$(pidof system_server)/maps)"
done
cat /proc/oplus_mem/swappiness_para
ls -laZ /dev/osvelte已知问题
- swap 占用仍低于对照机,收益尚未测得。 本版的 AOT 与 swappiness 两项都指向
“更敢用 swap、更少抖动”,但目前只有刚开机的样本,需要一段正常使用后的稳态数据
才能判断。 /data/misc/apexdata/com.android.art/dalvik-cache/仍为空。 原厂的 odrefresh
路径被镜像里那批移植者产物堵死,只读分区删不掉,只能用绑定替代;镜像里因此白占
约 340MB(system_ext)+ 60MB(my_stock)无法回收。servicemanager有 lazy 服务重试空转,5 个不存在的射频服务持续重试,占
6~7% 单核 ≈ 整机 1%。实测停用发起方毫无改善,已还原。根源是移植包仍把这台
无基带设备当双卡手机(声明telephony.ims、multisim.config=dsds)。oplus_synchronize仍不出货,四轮四崩已结案,见 4.0.3。- 手势 CE 存储的 hook 需要手工勾选作用域:
com.oplus.gesture未加入 LSPosed
作用域时仍会FATAL。
安装
见仓库 README。从 4.0.3 升级直接安装两个新包并重启即可,
无需卸载旧版。
v4.0.3 — 负载均衡从未触发、UX 线程登记被 SELinux 拦掉
v4.0.3
调度链修复发布:全部模块与配套 APK 统一为 4.0.3 / 400003。
本版的主线是一件此前没被发现的事 —— ColorOS 的调度信号在这台设备上传不到最终执行方。负载均衡从开机起就没跑过,UX 线程登记被 SELinux 拦着,帧组认出来了却不给 SurfaceFlinger 提频。三处都修了。
Note
本页对应的产物已于 2026-09-12 重新构建并覆盖同一 Release。变更集中在
OplusBSP-Modules 与 FixModule 两个包,其余产物未变。
Note
本次未变更内核镜像。boot 与 vendor_boot 沿用 v4.0.0,不需要重刷。
新增的 oplus_lb_bridge.ko 由 OPlus BSP 模块在 post-fs-data 装载,不进内核镜像。
相比 v4.0.2
sched_assist 的负载均衡从未被触发过
/proc/oplus_scheduler/sched_assist/lb_stat 的全部计数长期为 0。同 ColorOS 版本的对照机 PKX110 跑 26 小时是:
tick_hit 24,803,944 newidle_hit 114,913,338
tick_hit 基本等于调度 tick 次数,为 0 意味着函数体一次都没进过。
反汇编 oplus_cpu_sched_sched_assist.ko 后原因清楚了:
__oplus_tick_balance与__oplus_newidle_balance在__ksymtab里,是导出给外部模块调用的入口,模块内部没有任何调用者;- sched_assist 自己注册的
android_vh_scheduler_tick_handler只在 debug 打开时做 systrace,不碰负载均衡; - 入口处的门读的是
lb_enable,运行时值为 1 —— 门是开的,只是没人进。
调用方是 OPlus 打过补丁的 WALT。对照机的 sched_walt 出现在 oplus_bsp_sched_assist 的使用者列表里,本机的不在;kallsyms 里 walt 符号数 3177(本机)对 4164(对照机)。本机内核带的是高通原版 WALT,不会去调那两个入口。
后果是 UX 线程(动画、输入、渲染)不会被主动迁到空闲核 —— 长期被归因为「亮屏一刻卡」「锁屏动画卡」的那类现象,机制上就在这里。
做法:新增自编内核模块 oplus_lb_bridge,把 tick 入口接回 android_vh_scheduler_tick。
修复后(本机 65 分钟 / 对照机 28 小时,同口径):
| 指标 | 本机 修复前 | 本机 修复后 | 对照机 PKX110 |
|---|---|---|---|
tick_hit / 秒 |
0 | 345 | 274 |
tick_pull_runnable_ux |
0 | 22,037 | 9,834 |
newidle_hit |
0 | 0 | 114,913,338 |
Note
newidle 那半边接不了:android_rvh_sched_newidle_balance 是受限 hook,GKI 的
android_rvh_probe_register() 在 static key 已翻起时返回 -EBUSY,即只允许一个探针,
而高通 WALT 已经占用。本模块只接 tick 这一半。
实现上踩了一个坑,记录下来:第一版把 __oplus_tick_balance 直接注册成探针,insmod 瞬间 panic ——
Kernel panic - not syncing: Oops - CFI: Fatal exception in interrupt
__oplus_tick_balance+0x0/0x354 at __traceiter_android_vh_scheduler_tick+0x40/0x68
崩在进入函数体之前,是 kCFI 拦的。__traceiter_* 通过函数指针间接调用探针会校验目标的 kCFI 类型标识前缀,而该函数在 OPlus 源码里只被直接调用、地址从未被取过,编译器没给它生成那个前缀。改为在模块内加一层签名一致的转接函数、转接体里直接调用即可 —— 直接调用不走 CFI 校验。
三级撤销:echo 0 > /proc/oplus_scheduler/sched_assist/lb_enable(免重启)→ rmmod oplus_lb_bridge → 从模块清单删掉该行。
移植时丢掉的 SELinux 放行
对照机 3.5 个月的日志里 avc: denied 合计 10 条,且全是良性的 zygote socket。本机 20 分钟 323 条,其中 331 次判定里除 2 条外全是 permissive=0 —— 真的在拦。
被拦的两类正好是上一节那条链的另一半:
untrusted_app / untrusted_app_all -> oplus_scheduler_sched_assist_proc {read write} (im_flag, ux_task)
surfaceflinger -> oplus_ux_task_app_proc {read write}
system_app / system_server -> proc_frame_boost_sys_ctrl {read write}
cameraserver / audioserver / … -> proc_frame_boost_ctrl {ioctl}
应用与系统服务把关键线程的 tid 写进 ux_task / ux_task_app,sched_assist 据此标 UX。**被拦就等于线程从未登记成功,均衡器接通了也挑不出它们来迁移。**其中 surfaceflinger 被拦在 sched_assist 目录门口这条影响最直接。
/proc/oplus_frame_boost/* 这组节点是本项目的 ua_cpu_ioctl 建出来的,标签对、策略里却没有对应 allow —— 属于「节点装回来了、规则没跟上」。
同批还补了两处与调度无关的:system_server 的 Athena 内存回收写入(zygote_tmpfs / vndbinder_device),以及 audioserver 读应用音频线程调度参数(实时优先级提升)。
修复后在负载测试下,上述三类拒绝全部归零。
中途发现
untrusted_app_30是独立的 SELinux 类型而非untrusted_app的实例 ——
AOSP 按 targetSdk 分出untrusted_app_25/27/29/30/32一串类型,逐个补是打地鼠。
最终改用 AOSP 自带的untrusted_app_all属性一次覆盖。
手势服务开机崩溃循环
com.oplus.gesture 在开机 13 秒内连崩 4 次,对照机全程零崩溃:
IllegalStateException: SharedPreferences in credential encrypted storage
are not available until after user is unlocked
at ScreenOffGestureService.onCreate → ActionContentProvider.query
→ GestureUtil.getDefaultGestureSwitch
用户解锁前就有人查 ActionContentProvider,provider 去读自己的 SharedPreferences,撞上 CE 存储未就绪。
现有的 getStorageContext 钩子只覆盖了走它的那条路。本版补一条:锁屏期间把 ContextImpl.getSharedPreferences 改道到 DE 存储(靠 isDeviceProtectedStorage() 防重入),解锁后不再改道,读到的仍是原厂 CE 数据。com.oplus.gesture 已加入 Hook 的推荐作用域,需在 LSPosed 里勾选后生效。
Soter Key 开机自愈
参照第三方模块「修复Key状态」的 Soter 流程重新实现并并入修复模块:等用户解锁 → 打开工程模式 RPMB 状态页 → 停 vendor.soter → pm clear com.tencent.soter.soterserver → 重启服务 → 再触发一次状态页。
两处有意偏离上游:服务名改为扫 init.svc.*soter* 而不是硬编码候选表;收尾补一次 force-stop,不把工程模式页面留在屏幕上。
开关:persist.sys.aclaniakea.soter_fix=0 整段跳过,persist.sys.aclaniakea.soter_fix_ui=0 只做 stop/clear/start。
Warning
**这是能力移植,不是已验证的故障修复。**本机没有任何证据表明 Soter 当前是坏的:
logcat 全缓冲里 soter 相关 0 条、无 error,vendor.soter 一直 running。
若使用指纹支付后出现需要重新验证的情况,第一个该关掉的就是这里。
RKP 那半边有意不移植 —— 它要写 persist 分区、依赖本项目没有的 KmInstallKeybox
二进制,而本机的证明链本来就走 tricky_store。
UX 标记翻译成 WALT 认识的形式
补完负载均衡之后还剩一段断链:最终「下一个跑哪个任务」的决策归高通
sched_walt 的 walt_cfs_replace_next_task_fair(),而它不认 OPlus 的 UX 状态。
那个钩子是受限 hook(单探针),抢不过来,也不该抢——它本身就是最终决策者。
做法是不抢钩子、改喂它:在普通的 android_vh_scheduler_tick 上判断当前任务是否
被 OPlus 标成 UX,是就调用 WALT 原生的 set_task_boost() 续一个短期 boost,
之后的选核与抢占全部由 WALT 自己完成。
boost_type 取 1(TASK_BOOST_ON_MID)而非最激进的 3。本机拓扑是
cpu0 capacity 379(唯一弱核)、cpu1-4 是 867、cpu5 是 1024;UI 线程一旦落到
cpu0 就只剩中核 44% 的算力,抬到中簇即可,不必用 type 3 的 STRICT_MAX +
MVP 强制(后者带 12ms MVP 执行上限,超限会被降级)。
Warning
**这个桥的收益没有被测量证实。**前后八轮 A/B(五轮 Perfetto FrameTimeline +
三轮 SurfaceFlinger timestats)没有一致方向:基线漂移远大于效应,同为「关桥」
的样本,帧间隔尾部在两轮之间从 0.3% 摆到 8.7%,且样本越靠后越差。刷新率已
排除(全程稳定 150Hz、主导间隔 6ms)。
启用它的依据是「把一条确实断掉的原厂链路接回去」,不是「实测更快」。
三种关法,由轻到重:
echo 0 > /sys/module/oplus_walt_bridge/parameters/enable(免重启)、
touch <模块目录>/disable-walt-bridge 后重启、rmmod oplus_walt_bridge。
帧组不给 SurfaceFlinger 提频
/proc/oplus_frame_boost/info 显示帧组识别是正常的(RenderThread + 应用主线程、
SF COMPOSITION GROUP 都在),但 stune_boost 表里 grp5-9 缺两项:
| 本机 | 对照机 PKX110 | |
|---|---|---|
| grp1-4 | 相同 | 相同 |
| grp5-9 | 9 项 | 11~12 项,多出 sf_migr_gpu:30 sf_freq_gpu:30 |
也就是应用帧组活跃时,本机不给 SurfaceFlinger 任何提频与迁移加成,合成跟不上
就直接是掉帧。这两个值由框架运行时决定,两台设备的 /system /vendor /product
里都搜不到对应配置文件,所以只能在框架写完之后补写——放在 boot_completed 之后
执行。写入格式 <grp_id> <索引> <值> 是从 ua_cpu_ioctl.ko 的
proc_stune_boost_write 实测出来的。实测五组全部写入成功,经 20 秒滑动与一次应用
切换未被框架改回。
8GB 内存档交还原厂
v4.0.2 加的那一档(/apps/active 与 /apps/systemserver 的 app_score 写 0,
把桌面、SystemUI、system_server 整个排除在 zram 压缩之外)已撤销,全树交还原厂的
300。当时只测了唤醒瞬间的换入量,代价在长时间使用后才显出来:
平板 swap 使用率 50%(4119/8191 MB) 对照机 61%(7500/12287 MB)
平板 AnonPages 916 MB 对照机 2211 MB
把三个最大的常驻进程整个豁免,等于让内存最紧的机器反而最不敢用 swap。原注释里
写着「若出现后台留存变差,第一个该回退的就是这里」——就是这次。
移除 oplus_resctrl
清单末尾模块会间歇性 insmod 失败,根因是 per-CPU 模块预留耗尽:
percpu_modalloc() 只从 PERCPU_MODULE_RESERVE(编译期常量,约 8KB)分配,
不会退化到动态 chunk,且在我们之前已有四百多个 vendor 模块先吃过一轮。
逐个量 .data..percpu 段后发现,清单里只有 6 个模块占预留、合计 4208 B,
而 oplus_resctrl 一个就要 3408 B(81%)。移除依据三条:对照机 694 个已加载模块
里没有任何 resctrl 字样;清单内无任何模块依赖它;它建的是
/proc/oplus_resctrl/{ioc_dist_read,ioc_dist_write,iocost_ppm}——blk-iocost 的
IO 开销控制器,不是加载器旧注释写的「cache/带宽分区」(该描述一并更正),
本机也没有任何东西配置这三个节点。
让出这 3408 B 之后,对照机确实有的 oplus_bsp_game_opt 就能稳定装上,
开机由 33 loaded / 1 failed 变为 33 loaded / 0 failed。.ko 仍保留在包里。
已知问题
- 桌面显存偏高:
com.android.launcher的 Skia 暂存渲染目标缓存长时间运行后可涨到约 900MB(对照机约 60MB)。真正的纹理缓存两台相同,差异全在暂存目标没被复用;TRIM_MEMORY_COMPLETE只能清掉其中一小部分。这是桌面应用内部行为,系统属性层面没有对应旋钮,本版未处理。 - 属性枚举拒绝:每次进程 spawn 会有一轮遍历全部属性上下文的读取,在受限域上产生一批
avc: denied。已确认是本机独有行为(对照机策略同样拒绝,只是从不发生这种枚举),但未定位到发起者。影响是日志噪声与少量 spawn 开销,不构成功能损坏。 - 锁屏动态壁纸打拍:沿用 v4.0.2 的结论,
144 ÷ 60 = 2.4不整除导致的固定节拍,与性能无关,无解。 - 锁的 UX 优先级继承仍然缺失:对应的 OPlus 模块(
oplus_synchronize,即对照机上的oplus_locking_strategy)试过四轮,四轮都 kernel panic。期间定位并修掉三处真实根因——mutex_list_add_ux把链表中间节点当链表头、rwsem_list_add_ux同类问题且无条件返回已入链、owner可为 NULL 却直接喂给set_inherit_ux——但每修完一处就冒出下一处。本机/sys/fs/pstore/console-ramoops-0的 ECC 已损,取不到调用栈,继续下去等于盲修,故结案。源码与三处修复存档在kernel-compat/oplus_synchronize/,不随模块加载。 servicemanager持续占用约 1.26% 单核(对照机 0.026%):本机ro.carrier=wifi-only却带着 OPD2513 的双卡射频配置,vintf 声明了ISubsys/default而没有任何 init 服务提供它,于是每秒两次 lazy-start 失败。占 6 核的 0.2%,未处理。- 每次进程 spawn 会有一轮遍历全部属性上下文的读取,在受限域上产生一批
avc: denied。已确认是本机独有行为(对照机策略同样拒绝,只是从不发生这种枚举),但未定位到发起者。影响是日志噪声与少量 spawn 开销。 - 沿用 v4.0.1:移植包重打包 vendor 时丢了
/vendor/bin/qms与/vendor/bin/qcc-vendor的 SELinux 标签,须在重打包时对vendor_file_contexts执行一次setfiles。本机无本地调制解调器,功能上无损失。
安装或升级
请使用同一 v4.0.3 Release 的产物。内核沿用 v4.0.0,不需要重刷。
安装完 KernelSU 模块与 APK 后执行一次完整重启,不要仅重启 zygote。
v4.0.2 — 相机跨设备闪退修复、8GB 内存档
v4.0.2
v4.0.1 之上的修正发布:全部模块与配套 APK 统一为 4.0.2 / 400002。两处功能改动,其余模块仅为版本对齐重建。
Note
本次未变更内核。boot 与 vendor_boot 沿用 v4.0.0,不需要重刷。
相比 v4.0.1
ZUI 相机在其他设备上闪退
有用户反馈相机一打开就闪退,崩溃日志的根因是:
java.lang.NullPointerException: getSupportedModes() must not be null
at com.zui.camera.ui.mode.ModeRecyclerView.generateModeList(ModeRecyclerView.kt:241)
ZUI 相机按 Build.DEVICE 在内置 JSON 里查本机支持哪些拍摄模式,查不到就返回 null,Kotlin 空断言直接抛 NPE。相机模块的 zygisk 身份层本应把该进程的机型属性改写成 Lenovo,但它把开发机上 com.zui.camera 的 UID 写死成了常量——UID 由安装顺序决定,换台设备就对不上,身份层不生效,相机读到的仍是移植包的 OP6547L1。
现改为在 postAppSpecialize 读 /proc/self/comm 按进程名识别。该值由 AOSP 的 SpecializeCommon() 在这一步之前设好,读它不需要任何权限,因此与设备、与 zygisk 实现(Magisk / ReZygisk / Zygisk Next)都无关。注册改为 ABI v4→v3→v2 逐级回退,被拒时不再静默失效。
这不是 hybrid_mount 或 OverlayFS 的问题——先前的推测已被崩溃日志推翻。
8GB 内存档
症状:长时间锁屏后点亮,锁屏动态壁纸与解锁动画明显卡顿。
测量:息屏 120 秒后点亮的 6 秒窗口内,系统换入 712MB、直接回收 573MB——直接回收发生在申请内存的那个线程上下文里,即 UI 线程被同步阻塞。按进程拆分后,桌面、SystemUI、system_server 三者合计有 1GB 以上躺在 zram 里。
原因:ColorOS 的 swapd 按 app_score 分级,score 100-399 这档允许把 80% 内存压进 zram,而所有 memcg 分组默认停在 300。已用真机 ColorOS 对照确认原厂同样如此,所以不是移植缺陷;问题在于原厂把 min_free_kbytes、avail_buffers 都按内存容量分了档,唯独这个压缩比例不随内存变。同一策略在 11GB 机器上还剩 3.5GB 余量,在 7.4GiB 的本机就开始抖动。
改动:仅在 RamSizeGB <= 8 的设备上,把 /apps/active 与 /apps/systemserver 的 app_score 写 0(level 0,不压缩)。/apps/inactive 保持原厂 300——那里装着几十个纯缓存应用,整桶豁免等于在 8GB 机器上放弃 swap。12GB 及以上完全保持原厂行为。
同一次开机内 A/B(息屏 90 秒后唤醒):
| 指标 | 原厂 score=300 |
本档 score=0 |
|---|---|---|
换入 pswpin |
58.6 MB | 17.6 MB(−70%) |
直接回收 pgsteal_direct |
79.7 MB | 0 |
主缺页 pgmajfault |
15731 | 5127(−67%) |
代价:MemAvailable 约 −200MB,两组用量收敛,零 LMK/OOM 击杀。
Warning
这是主动偏离原厂,不是恢复原厂。若出现后台应用留存变差或击杀增多,第一个该回退的就是这里:把两组 app_score 写回 300 即可。
自定义键「选择应用」深色模式无卡片背景
亮色模式一直正常,深色下整片纯黑。原厂的做法不是给列表加卡片容器,而是逐行画:
activity_app_picker 里列表直接放在 FrameLayout 中,行布局也没有背景,Settings 备了
card_list_item_{head,body,foot,full}_bg 四件套按位置取用。原实现反过来做成了容器卡片。
改为逐行后仍不显示:分支探针确认资源名解析得到、getDrawable() 非空、setBackground()
执行,行内采样仍是 #000000,而同一位置强制不透明填充能正常渲染。原因是这些 shape 填充
?attr/couiColorCard,在此 context 下用 Resources#getColor 读取时深色返回不透明黑
—— ColorOS 有运行时 RRO 主题覆盖,资源表记录的 #1affffff 不是实际返回值。
最终改用 Settings 自己页面的取色入口 COUIContextUtil.getAttrColor。修复后与原厂应用管理
逐像素一致:深色行 (26,26,26) / 页面 (0,0,0),亮色行 (255,255,255) / 页面 (240,241,242)。
缓存进程预算交还原厂分档
三个遗留调试属性(persist.sys.aclaniakea.max_cached、persist.sys.max_cached_test、
persist.sys.oplus.max_cached_test)把 AMS 的缓存进程上限锁在 24 —— 比 AOSP 默认的 32
还低,是原厂 ColorOS 的 1/5(参考机 PKX110 为 128)。它们已写进持久化属性存储,每次开机
由 init 恢复。
后果:缓存预算腰斩后,任何掉到 cached 的进程都会被迅速清掉。实测全局搜索
com.heytap.quicksearchbox 只活了 116~258 秒,而同一次开机里桌面活了 41670 秒 ——
「全局搜索呼不出来」就是它在冷启动。
本版只把覆盖拿掉、不设任何值,交还原厂按内存分档:CUR_MAX_CACHED_PROCESSES 24 → 48、
CUR_MAX_EMPTY_PROCESSES 12 → 24、CUR_TRIM_CACHED_PROCESSES 4 → 8。
Scene 调度模块:陈旧锁导致整层静默停摆
调度模块用 mkdir 做互斥、只靠 EXIT trap 释放。进程被杀或设备在 apply 中途重启时 trap
不执行,锁目录永久留下。实机上 apply.lock 的时间戳与最后一次成功 apply 完全相同
(2026-08-25 23:02),此后两周内每一次档位应用都空转 20 次后 exit 4,且不写任何日志 ——
增强调度这一层实际上是死的。
已改为:锁内记录持有者 pid,持有者进程已不在就按陈旧锁清掉;放弃时必须写日志;trap 覆盖
INT/TERM/HUP。同时修 write_node 的比较 —— 多值 sysfs 节点读回是 Tab 分隔而写入是空格,
逐字符比较把每一次成功写入都误报成 write rejected(实机日志里 5 条全是假的),真正的失败
反而被淹没。
已知问题:锁屏动态壁纸打拍(无解,非性能问题)
动态壁纸 com.heytap.colorfulengine 恒定以 60fps 渲染,而面板跑 144Hz。144 ÷ 60 = 2.4
不是整数,每帧只能落在第 2 或第 3 个 vsync 上,形成固定的 3-2-3-2-2 节拍。实测
SurfaceFlinger 图层呈现间隔:144Hz 下节拍 {2:72, 3:48}、抖动 3.95ms;强制 120Hz 下前 21 个
间隔全是 2、完全均匀。
与性能无关 —— GPU 下限 231→578 MHz 四轮交替对照零差异。也无法用 per-package 刷新率策略
规避:ColorOS 的 OplusRefreshRatePolicyImpl 按置顶 Activity 的包名查表,而锁屏是 SystemUI
的窗口不是 Activity,背后 resumed 的仍是桌面。要消除只能把桌面降到 120Hz,代价大于收益。
参考机 PKX110 面板本身是 120Hz(120÷60=2 整除),原厂从未遇到这个组合。
修复与打包
exempt_persistent_memcg原实现只写/dev/memcg/apps/uid_$uid,而本机是 per-package 布局、该路径仅存在一个空组,整段是空转的;现改为从/proc/PID/cgroup读进程实际所在的 memcg。- 同一函数靠进程发现会漏掉开机时尚无 SystemUI 的
/apps/active,改为显式对齐两个原厂分层组。 build_all.sh补上把相机两个产物汇总到顶层releases/的步骤(v4.0.1 是手工拷的),并生成SHA256SUMS。
已知问题
沿用 v4.0.1:移植包重打包 vendor 时丢了 /vendor/bin/qms 与 /vendor/bin/qcc-vendor 的 SELinux 标签,须在重打包时对 vendor_file_contexts 执行一次 setfiles。本机无本地调制解调器,功能上无损失。
安装或升级
请使用同一 v4.0.2 Release 的产物。内核沿用 v4.0.0,不需要重刷。
安装完 KernelSU 模块与 APK 后执行一次完整重启,不要仅重启 zygote。
v4.0.1 — 前台掉帧减半、手写笔触感页重做
v4.0.1
v4.0.0 基线之上的修正发布:全部模块与配套 APK 统一为 4.0.1 / 400001,由当前源码重新构建。
Note
本次未变更内核。Release 中的 boot 与 vendor_boot 与 v4.0.0 内容相同,仍须成对刷入。
相比 v4.0.0
前台掉帧减半
桌面滑动掉帧率 12.49% → 6.23%,帧时间 p99 150ms → 48ms。按帧数归一后 Missed Vsync −53%、Slow UI thread −48%、Slow issue draw commands −59%、Slow bitmap uploads −77%。
gfxinfo framestats 逐阶段拆解把病灶指向调度而非 GPU(帧内中位 1.29ms)或内存(PSI some avg60 0.10):Vsync→HandleInput 这段纯调度延迟 p99 达 6.92ms,而 144Hz 的帧预算只有 6.95ms。
根子在核心拓扑——本机六核 1+4+1,cpu0 是唯一的 A520,实测 65% 忙并承接全部 WiFi 收包中断,而 top-app 原本包含它。改为沿用原厂给 SurfaceFlinger(sf 分组)的核集合(原厂本就把 cpu0 排除在 sf 之外),并打开 latency_sensitive。
手写笔触感反馈重做
原厂触感页的三个控件在这支笔上全是死路:书写反馈与振动强度写的是 ColorOS 专有特征,本机 GATT 没有;功能反馈的原厂接口是只打日志的空实现。现隐藏这三行与试写区,改为一个直连联想触觉通路的全局书写反馈开关,加五档笔触感模式。入口跟随连接状态置灰。
传输层同时修正两处会导致「振动整体消失」的问题:不再把书写开关命令翻译到联想的触觉总开关特征(带关闭语义时会让笔上所有振动断电);会话查找改为优先返回仍绑定在活动会话上的那一个(重连后残留的同 MAC 孤儿会话会让命令无人认领,1.8 秒后看门狗判死整条传输)。
system_server 的 AOT 产物失配
移植包换过 /system/framework/services.jar 的主 dex(zip CRC 变了)却没重建 oat 产物。ART 校验 services.vdex 的五个 location checksum 时只有主 dex 对不上,而它要求全部匹配,于是整份拒绝、退回从 jar 直读——system_server 的 18MB 主体一直在解释执行加 JIT。
代价可量化:Jit thread pool 累计占开机时间 5.4%(同代 ColorOS 对照机 0.167%),解锁瞬间 JIT 独占 system_server CPU 的 20.2%。
系统自身修不了:odrefresh 只检查文件存在性与 ART apex 版本,因此报告 "artifacts OK" 而从不重编;它编到 /data/misc/apexdata 的产物又会在下次开机被当作多余清理掉。同一个 checksum 也让 services.jar.prof 失效,默认的 speed-profile 只能产出空壳。
本版随包分发已编译好的产物,由 post-fs-data 绑定到 /system 侧,相同移植构建的设备装完重启即生效。若构建不同,ART 会拒绝该产物(表现与修复前一致,不会更糟),模块随后在开机三分钟后于后台自动重编,参数全部从运行中的系统读取,不硬编码机型。FixModule 体积因此由 89.8MB 增至 127.9MB。
Note
已确认:三个产物(.art / .odex / .vdex)全部被 ART 采纳,连续重启可复现。
未确认:对解锁掉帧与 system_server 占用的实际改善幅度——采样窗口内有用户交互干扰,故本说明不给出收益数字。
稳定性与开销
- 收敛充电控制节点权限:移植包把
charging_enable等一律开成全局可写,任何应用都能停掉充电。现去掉 other 写位,属主与读权限不变,两条既有写入路径不受影响。 - 应用建议自愈改为限速:原实现每 2.7 秒就启动一次 ART 虚拟机做无事发生的检查。限速后系统空闲期进程创建速率由 42/s 降至 19~24/s。
- 键盘自定义键:「选择应用」页的「显示系统应用」开关此前点了没反应,现就地重过滤列表。
已知问题
移植包重打包 vendor 时丢了 /vendor/bin/qms 与 /vendor/bin/qcc-vendor 的 SELinux 标签,init 因此拒绝注册对应服务,servicemanager 会持续尝试惰性启动五个射频/数据 AIDL 接口并失败。本机没有本地调制解调器,功能上无损失,但会产生约 5 次/秒的无效 init 往返。这是打包阶段缺陷,模块无法修复(init 解析 rc 早于模块挂载),须在重打包时对 vendor_file_contexts 执行一次 setfiles。
安装或升级
请使用同一 v4.0.1 Release 的产物。内核沿用 v4.0.0,不需要重刷。
安装完 KernelSU 模块与 APK 后执行一次完整重启,不要仅重启 zygote。
v4.0.0 — SM8650Q stable baseline
v4.0.0
面向 TB710FU / SM8650Q 的稳定基线发布。全部模块与配套 APK 统一为 4.0.0 / 400000,并以已在设备上验证的 droidspaces-r1+ 内核与阻塞版 vendor_boot 作为唯一正常引导链。
Warning
必须成对刷入 boot-ACLaniakea-SM8650Q-droidspaces-r1.img 与 vendor_boot-hyperSched-stub.img。vendor_boot-ColorOS16-original-TB710FU.img 是原始 ColorOS 回退镜像,只能与同来源原始 boot 一同用于回退,不可与本版本 boot 混刷。
相比 v3.2.1
交还原厂内存与性能路径
- 恢复并保留 ColorOS 原厂的 HybridSwap、内存扩展、性能 HAL、WALT 与 cpuctl 路径,模块不再覆盖 swappiness 或水位线。
- 修复移植框架的 UAF QoS 子调度器:设备缺少匹配的策略表,原先会让 system_server 反复查询空策略;现按原厂参考机的回退语义跳过该失败分支。
HMBIRD/sched_ext未作为正式功能启用,相关试验代码与镜像移至experimental/kernel-sched-ext/,不进入 Release 安装链。
r1+ 内核与 DroidSpaces
- 正式内核升级为
6.1.128-android14-11-sm8650q-droidspaces-r1+,补齐 DroidSpaces 所需的 User / PID / IPC / Network / Time namespace 与SYSVIPC、POSIX 消息队列。 - 保留并验证容器运行链所需的
ANDROID_BINDERFS、ashmem/memfd shim、OverlayFS、FUSE/FUSE-BPF、seccomp、io_uring、cgroup freezer、PSI 与 tmpfs ACL/xattr。 - 显示与音频仍由 DroidSpaces/AnLand 的 Android 侧桥接负责,本 Release 不宣称将其编入内核。
- 调度基线不变:sched_ext 与 HMBIRD 仍是隔离实验,未进入 r1+。
稳定性与硬件链路
- 延续相机 Provider 的 SIGPIPE 防护、CamX 动态深度标签兼容,以及 AON 与普通相机的生命周期仲裁。
- 延续 CryptoEng 10003 分流,查找设备、密码本与互传联系人由
FixModule统一提供。 - 延续手写笔 BLE/HID、电量/充电/磁吸状态与触觉桥接;手写笔三件套同步升级。
- ZUI 相机移植与兼容 Hook 同步升级,仍仅做应用级兼容,不替换相机 HAL。
Note
PortTuning-Module 已废弃且不再发布,其策略由主修复中恢复的原厂内存与性能路径替代。
安装或升级
- 备份现有
boot、vendor_boot与 KernelSU 配置。 - 在 bootloader 中依次刷入本版
boot与vendor_boot,重启。 - 通过 KernelSU 安装
FixModule与OplusBSP-Modules;手写笔、Scene、ZUI 相机按需安装。 - 安装所需 LSPosed Hook 与 APK,按 README 的推荐作用域启用。
- 执行一次完整重启,不要仅重启 zygote。
完整命令、回退边界与 SHA-256 见 README。
v3.2.1
v3.2.1
整合发布:所有模块与配套 APK 统一为 3.2.1 / 302001,CryptoEng 修复并入主修复模块。
Note
本次未变更内核。Release 中的 boot 与 vendor_boot 与 v3.2.0 内容相同,仍须成对刷入。
相比 v3.2.0
CryptoEng 并入主修复
FixModule内置 CryptoEng 分流代理:命令 10003 在本地实现,其余请求继续走已验证的软件 HAL 路径。- 安装主模块会停用旧的独立
cryptoeng_hal_fix,避免两个代理竞争同一 HAL 服务。 - 查找设备、密码本云同步与一加互传联系人所需的兼容路径保持不变。
构建与交付
- 全部模块、Hook 与 APK 由当前源码重新构建。
- 构建入口兼容仓库内最小 Android SDK,避免工作站缺少新版 build-tools 时无法复现。
- ZUI 相机的原厂 APK 仅作为构建输入与发布附件,不纳入源码仓库。
安装或升级
请使用同一 v3.2.1 Release 的产物。安装 FixModule 后不要再安装旧的 CryptoengHAL-Module。
安装完 KernelSU 模块与 APK 后执行一次完整重启,不要仅重启 zygote。

