Skip to content
This repository was archived by the owner on Oct 22, 2026. It is now read-only.

Releases: ACLaniakea/coloros-pad-fixes

ColorOS Pad Fixes v4.1.3

Choose a tag to compare

@ACLaniakea ACLaniakea released this 16 Sep 17:04

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

Choose a tag to compare

@ACLaniakea ACLaniakea released this 16 Sep 15:12

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 迁移至原厂对应的 /sf cpuset;不
    重启 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 内核

Choose a tag to compare

@ACLaniakea ACLaniakea released this 15 Sep 13:08

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 次/秒,对照机
20
114 次/秒。

开发中的 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_layout CRC 仍为 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 内核

Choose a tag to compare

@ACLaniakea ACLaniakea released this 14 Sep 09:08

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。但随后两项证据推翻了它:

  1. 原厂不用这套。 逐个扫过 ROM 里所有引用 kgsl/kgsl/proc 的组件
    (libAlgoProcess.so、memtrack-service、autochmod.sh、若干 sepolicy),
    全是只读统计,没有任何一个写 state;参照机命中同一批组件、同样只读,
    而且它的 proc/<pid>/ 下连 state 节点都没有。
  2. 收益兑现不了,代价正好落在用户抱怨的交互上。 待机腾出的内存没有消费者,
    而这笔钱要在下一次解锁时连本带利还:解锁窗口桌面的 95 分位帧时,熄屏回收过
    的两轮是 101ms / 121ms,没回收的那轮只有 24ms。桌面是唯一的显存大户,
    也是解锁时第一个重画的东西——对照机在解锁时桌面一帧都不重画。
    而且平板实测 内核击杀记录为 0、PSI some 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_layout CRC 保持
    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-r2

490 个模块应全部加载、0 熔断;dmesg 无 panic、无 avc 拒绝。

其余模块

随统一版本号重建,内容未变。

4.0.4 - 接回被移植弄断的 AOT 与内存链路

Choose a tag to compare

@ACLaniakea ACLaniakea released this 12 Sep 13:55

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 拦掉

Choose a tag to compare

@ACLaniakea ACLaniakea released this 11 Sep 12:43

ColorOS Pad Fixes — 联想小新 Pad Pro GT · SM8650Q

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 后原因清楚了:

  1. __oplus_tick_balance 与 __oplus_newidle_balance 在 __ksymtab 里,是导出给外部模块调用的入口,模块内部没有任何调用者;
  2. sched_assist 自己注册的 android_vh_scheduler_tick_handler 只在 debug 打开时做 systrace,不碰负载均衡;
  3. 入口处的门读的是 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 内存档

Choose a tag to compare

@ACLaniakea ACLaniakea released this 09 Sep 15:05

ColorOS Pad Fixes — 联想小新 Pad Pro GT · SM8650Q

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 — 前台掉帧减半、手写笔触感页重做

Choose a tag to compare

@ACLaniakea ACLaniakea released this 09 Sep 02:17

ColorOS Pad Fixes — 联想小新 Pad Pro GT · SM8650Q

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

Choose a tag to compare

@ACLaniakea ACLaniakea released this 07 Sep 09:15

ColorOS Pad Fixes — 联想小新 Pad Pro GT · SM8650Q

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 已废弃且不再发布,其策略由主修复中恢复的原厂内存与性能路径替代。

安装或升级

  1. 备份现有 boot、vendor_boot 与 KernelSU 配置。
  2. 在 bootloader 中依次刷入本版 boot 与 vendor_boot,重启。
  3. 通过 KernelSU 安装 FixModule 与 OplusBSP-Modules;手写笔、Scene、ZUI 相机按需安装。
  4. 安装所需 LSPosed Hook 与 APK,按 README 的推荐作用域启用。
  5. 执行一次完整重启,不要仅重启 zygote。

完整命令、回退边界与 SHA-256 见 README。

微信赞助码

v3.2.1

Choose a tag to compare

@ACLaniakea ACLaniakea released this 03 Sep 05:20

ColorOS Pad Fixes — 联想小新 Pad Pro GT · SM8650Q

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。

微信赞助码