Skip to content

Releases: yigenhuobah/cloudmusictool

2.4.9

Choose a tag to compare

@yigenhuobah yigenhuobah released this 02 Nov 12:13

修复

  • UI-04 顶部频道过滤导致「我的 → 最近」闪退(issue #5):MusicTabLayout.addTab 兜底原先按「不在保留清单里」删 tab,但该类被「我的音乐 / 最近播放」等页面复用;误删后 TabLayout 子 View 数与 PagerAdapter 页数不一致,populateFromPagerAdapter 抛 IndexOutOfBoundsException: index=2 count=1。现在兜底只作用于首页 tab 容器实例,并且只移除本次数据层真正过滤掉的标题。
  • 新增 TopTabHooksTest 回归用例:记录删除标题、非首页 MusicTabLayout 一律放行。

2.4.8

Choose a tag to compare

@yigenhuobah yigenhuobah released this 01 Nov 09:43

诊断轮(内置诊断 + 对齐,27 项工作项全修)。明细见仓库 CHANGELOG 对应条目与提交记录。

新增

  • 崩溃自动捕获:模块安装时包装宿主未捕获异常处理器(透传原 handler,不影响应用自有上报),最近 3 条崩溃(时间/线程/异常类+前 2 帧)随诊断回传,诊断页新增「最近崩溃」卡片——报障不再需要 adb。
  • 导出诊断包:诊断页新增分享按钮,一键聚合模块版本/系统/框架 API/目标版本/功能状态/最近命中/最近崩溃,走系统分享面板。

修复

  • 「我的页」自定义页补 onDestroy 清理(WriteGate + 在途刷新作废)。

说明

  • crash 通道为 HookState JSON 根级 crashes 数组;QB/QM/TB 为 crash0/1/2 平铺键——载体差异源于回传协议不同,语义同构(最近 3 条、240 字符截断、空串清残留)。

2.4.7

Choose a tag to compare

@yigenhuobah yigenhuobah released this 01 Nov 06:16

四模块深度审查修复轮(130 项发现,本模块 53 项中 52 项修复、1 项经实跑证伪豁免)。全量明细见仓库 CHANGELOG 对应条目与提交记录。

修复

  • 9.6.15 版本门控失配(high):BottomTabHooks/MineBackgroundHooks 不再用 versionCode == 9006013 判等,9.6.15 恢复 UI-05 底栏过滤与 EN-01 全屏链路;TargetProfile.findMethodSpec 修正改名后挂载点的 critical 判定。
  • 会话协议:session 改为身份比较(带进程随机后缀),时钟回拨不再整批丢弃回传;未来时间戳超过 5 分钟判过期。
  • 诊断口径:installer 异常计入 failed/criticalFailed,失败横幅不再漏报整体失效;DexKit native 加载与扫描失败增加负缓存,未适配版本不再主线程全盘扫描。
  • hook 语义:chain.proceed() 恢复单次调用(移出 try,禁止 catch 内二次 proceed);配置写回补 generation 回滚;hit 限流键收敛、hookNull 返回类型校验。
  • 其余:JSON 过滤支持对象级 blockCode、搜索广告卡隐藏、启动延迟重复投递修复,以及测试质量与死代码清理。

2.4.6

Choose a tag to compare

@yigenhuobah yigenhuobah released this 31 Oct 13:33

UI-03 首页定制新增两个可勾选项。

新增

  • 首页定制新增「搜索频道入口」「为你专属推荐(更多推荐)」两个可勾选项:
    对应网易云 9.6.13 首页 scan 日志中的 PAGE_RECOMMEND_SEARCH_CHANNEL_ENTRY
    与 PAGE_RECOMMEND_MORE_RCMD 两个 block code,追加在选项列表末尾,
    不影响旧选项索引;新增对应纯 JVM 单测锁定匹配行为。

注意

  • 这两个 block 只在宿主下发对应 AB / 推荐流时存在。部分账号的首页数据流中
    不含它们(9.6.15 真机实测 UI-03 cache scan ... no-match),勾选后可能
    没有可观察效果;选项只影响 UI-03 的过滤清单,不会误伤其他 block。

验证

  • 单测 257 个用例通过(0 失败 / 0 跳过);lint 0 error。
  • 真机(25102RKBEC / 网易云 9.6.15):2.4.6 覆盖安装后状态卡
    「目标版本 9.6.15 · 已注入目标应用」,profile mounts=145、
    runtime hooks installed 4/4;两个新选项可勾选并持久化;
    当前账号首页数据流不含这两个 block,端到端 filtered 不可构造;
    AD-01、UI-02、EN-01、PV-01~06 回归通过,无 FATAL/ANR。

2.4.5

Choose a tag to compare

@yigenhuobah yigenhuobah released this 29 Oct 14:17

深度代码评审第 4 轮(Phase 2–5):调度、配置写入、首页/背景热路径与诊断链路
加固,并新增网易云 9.6.15 兼容。

新增

  • 配置写入结果与异步提交(Phase 3):ConfigStore 引入 WriteResult
    (SAVED / REJECTED / UNAVAILABLE / FAILED),开关与多选写入改为
    后台单线程队列 + 异步 commit,真实结果回主线程。框架未连接时设置页、
    首页定制的开关置灰并提示;远端拒绝时开关/多选回滚并提示「保存失败,
    设置未生效」。设置页、实验页、首页定制的 remote prefs 读取与桌面图标
    组件状态读写全部移出主线程;桌面图标开关失败时回滚并提示。
  • 首页 block token 缓存(Phase 4):HomeBlockHooks 按 block 身份
    (WeakHashMap 弱键)缓存已提取的 positionCode / moduleKey,滚动时不再
    重复反射与正则;只有 String、org.json、Map/Collection 才序列化,任意
    宿主对象不再调用不可控的 toString。
  • 「我的」页背景源指纹(Phase 4):共享目录不可读、走 Provider 兜底时,
    通过 StatusProvider.query 读取内部图片 length / lastModified 指纹,
    换图或清除后能及时让缓存失效。
  • 运行时 ClassLoader 校验(Phase 4):RuntimeHookBootstrap 在安装运行时
    UI hook 前用 3 个宿主类探测 ClassLoader;Tinker 中间态或异常 loader 不执行
    installer 并重置标志,等后续 Activity 重试,避免 hook 挂在无效 loader 上。
  • 诊断会话与新鲜度(Phase 5):回传新增 session(目标进程启动时刻);
    模块侧丢弃迟到的旧会话整包回写;超过 10 分钟没有新回写时诊断页标记
    「数据已过期」,不再把旧快照当成健康数据。
  • 工具链:check-mounts.sh 记录 APK 路径/大小/mtime/SHA-256,同路径
    替换 APK 时丢弃旧临时结果;release.sh 在未安装 gh 时跳过官方仓资产
    SHA-256 校验并明确告警。

修复

  • 冷启动首报 context 未就绪:目标进程 context 未就绪时,
    TargetProcessPublisher 原先直接丢弃本次状态快照,诊断页在无后续事件时
    可能长期为空。现改为按 1s/2s/4s 有界重试最多 3 次,同一通道只保留一条
    重试链;成功、短路或重试耗尽都会取消在途任务。快照幂等,重复发送不会
    产生副作用,仅修复回传时机。
  • Profile 映射签名校验:HookKit 使用 Profile 映射方法前校验参数与返回
    类型;不匹配时输出 warn 并回退常规查找,避免挂到同名的错误重载方法。
  • DexKit 弱缓存:bridge 与 class 缓存的值改为 WeakReference。此前
    WeakHashMap 的弱键被强 value 反向引用,Tinker 热修 ClassLoader 无法回收。
  • 重试取消与单调时钟(Phase 2):TargetProcessPublisher 在发送成功、
    短路或重试耗尽时取消已排队的重试任务,避免状态已回传后迟到任务再次发送;
    PublishThrottle 的窗口判定改为 synchronized,消除「关窗消费 pending」
    与并发 decide 的竞争;生产时钟改用 nanoTime 单调毫秒,墙钟回拨不再吞
    事件、向前跳变不再重复发送。
  • ExperimentState 超长条目(Phase 2):key / group / source 任一超过协议
    上限(256 字符)时整条跳过并只告警一次。StatusProvider 对超长字符串是整包
    拒绝,跳过单条可保留其它 experiments 数据。
  • 「我的」页背景共享 Bitmap:清除背景时不再主动 recycle 进程级共享
    位图,只清引用交给 GC,修复其它页面继续绘制时的
    Canvas: trying to use a recycled bitmap 崩溃。
  • 失败横幅误报(Phase 5):failedFeatureCount 只统计主进程、TTL 内、
    已启用且「expected > 0 且 installed <= 0」或 criticalFailed > 0 的功能;
    普通 lastFailure 只作诊断。expected=0 的功能(如实验面板)不再计入。
  • 设置页旧快照覆盖(Phase 3):后台读取结果用 generation 丢弃过期快照;
    用户刚修改的开关/多选不会被更早的读取结果回写覆盖。

诊断

  • 诊断页数据来源新增「数据已过期:超过 10 分钟未收到目标进程回写」。
  • 回传 payload 根键白名单新增 session;迟到的旧会话回写记录
    status report ignored: stale session。
  • Profile 映射签名不匹配、运行时 loader 不可用、experiments 条目超长均输出
    明确的 warn 日志,便于定位适配问题。
  • 异常横幅只认 critical 挂载失败,可选挂载点改名不再把整个功能判死。

兼容

  • 网易云 9.6.15:9.6.15(versionCode 9006015)复用 9.6.13 的挂载点集合;
    2026-10-29 对 9.6.15 base.apk 全量体检 145/145 OK。版本门禁与「关于」页
    展示 9.6.08 / 9.6.13 / 9.6.15;未适配版本仍 fail-open。

已知限制

  • 底栏保留清单无法去掉「首页」Tab(9.6.13/9.6.15 主页面初始化依赖首页,
    强行删除会导致启动卡死)。
  • UI-03 的隐藏清单基于旧版 block code;9.6.13/9.6.15 首页新增的
    PAGE_RECOMMEND_SEARCH_TOP_BANNER / SEARCH_CHANNEL_ENTRY / MORE_RCMD
    等 code 需要在新版首页定制里勾选对应项才会隐藏。
  • 「我的页背景」清除后宿主侧 validType=4 注入不会回滚(与 2.4.2 一致),
    清除后如仍显示背景可重启网易云。
  • 9.6.15 复用 9.6.13 Profile,目前只完成挂载点静态体检,未做 9.6.15 单独
    真机验收;如 9.6.15 后续小版本改动类/方法坐标,需要重新体检。
  • 诊断数据 TTL 为 10 分钟且不发送心跳:目标进程空闲超过 10 分钟会显示
    「数据已过期」,这是设计内的「未知」状态,不是故障。
  • 异常横幅只统计 critical 挂载失败;非 critical 子项失败仅出现在诊断页,
    不会触发横幅。

验证

  • :app:testDebugUnitTest:252 个用例通过;:app:lintDebug、
    :app:assembleRelease 通过。
  • 9.6.15 挂载体检 145/145 OK(profile9613.json + --allow-version,
    RESULT: OK=145 GONE=0 ERROR=0)。
  • tools/verify-apk.sh PASS:versionCode=15 / versionName=2.4.5,签名证书
    SHA-256 eea85cac2aee030a28a2fe1e6f5b4e3e3c9448b674e53ec5bf88c3ea09d08925,
    R8 keep 与 Xposed 元数据全部通过。
  • APK:app/build/outputs/apk/release/cloudmusictool-2.4.5.apk,
    4,253,165 字节(约 4.06 MiB),SHA-256
    7184566341875033ad704208459624a9a7dd817ced708564cb5edd430b6ad62e。

2.4.4

Choose a tag to compare

@yigenhuobah yigenhuobah released this 26 Oct 17:20

网易云 9.6.13 三项适配(UI-03 / UI-05 / EN-01 第二层)。三项均已在真机
25102RKBEC / Android 17 / LSPosed 2.2.1 / 网易云 9.6.13 验证。

修复

  • 9.6.13 UI-03 首页模块净化:MixContainerData.getResources() 的元素是
    com.netease.luna.cm.container.Block,旧逻辑只认 DslBlock#getDslWrapperModel,
    对 9.6.13 首页混排的 NativeBlock / RnBlock 完全不命中。现主匹配改为
    Block.getPositionCode(),DslBlock 保留 originData 正则兜底,NativeBlock
    补充 nativeData / originServerData 兜底;隐藏清单新增 9.6.13 的 6 个
    block code(PAGE_RECOMMEND_BANNER_0 / GREETING / NOTE /
    PODCAST_NARROW_SCENE / SEARCH_TOP_BANNER / SECONDARY_TAB)。
    getBlockCodeOrderList() 同步按隐藏清单过滤(只影响下一次分页请求)。
    真机验证:配置的旧 30 项 code 命中时首页顶部对应卡片消失
    (resources filtered 9/9)。
  • 9.6.13 UI-05 底部导航精简:9.6.13 底栏列表构建点是
    tf0.o$a#y(List<BottomTabInfoVO>, Z);旧的 rh0.c.c 返回的是
    List<Drawable>(drawable 工厂),过滤它只会让图标错位、不能删 tab。
    现改挂 tf0.o$a#y 过滤入参,state 与 drawable 同源缩短;tf0.o$a 为
    9.6.13 专属挂载点,按 Profile 门控(9.6.08 不查找,避免诊断误报)。
    首页 Tab 始终保留:网易云主页面以首页为初始 tab,把首页从底栏删掉会让
    导航初始化卡住、启动页一直不消失(真机复现并修复)。保留清单不再包含首页时
    结果为「首页 + 保留清单」。
    真机验证:保留 {搜索, 关注} 时底栏为「首页 / 搜索 / 关注」
    (filtered from 4 to 3 tabs),正常进入首页。
  • 9.6.13 EN-01 我的页自定义背景(第二层调度点):MyMusicProxyFragment
    类并未消失——9.6.08 的 oc()Z(RN 门禁)在 9.6.13 改名为 kc()Z,
    而同名的 oc()V 只负责启动协程,旧 hook 对它返回 false 完全无效。
    现改为 hook kc()Z 返回 false 强制原生页(9.6.08 仍回退 oc()Z),
    并新增只读探针记录 sg.s() 结果与 hc() 最终创建的 Fragment。
    修复 9.6.13 已失配的反射(pe() → pe(Activity);删除 9.6.13 不存在的
    W1(boolean) / kd(String) 分支,9.6.08 保留原路径)。
    真机验证:kc=false 强制原生页、sg.s=true、
    hc fragment=MyMusicFragmentV4、本地背景贴图与内容区 scrim 全部生效。
  • 共享基础设施(三项共用):9.6.13 运行时使用 Tinker
    DelegateLastClassLoader(tinker_classN.apk),模块启动时的 ClassLoader
    与运行时不同。现提供 RuntimeHookBootstrap 在首个 Activity#onCreate
    用运行时 ClassLoader 统一安装 UI-03 / UI-05 / EN-01(UI-04 已在 2.4.3
    使用同机制);MountResolver 缓存按 ClassLoader 隔离;HookState 新增
    entry(入口调用)计数并区分 hit(过滤生效)计数,运行时安装后重算
    unavailable。
  • 诊断:getBlockCodeOrderList / getResources / getBlockList /
    底栏列表构建入口均记录 entry;getResources 无命中时按 10 秒限流打印
    block 运行时类型与 positionCode 样本,便于后续版本适配。

已知限制

  • 底栏保留清单无法去掉「首页」Tab(9.6.13 主页面初始化依赖首页,
    强行删除会导致启动卡死);首页定制页新增的「云村 (social)」「发布
    (publish)」按 tabCode 匹配 9.6.13 新增 tab。
  • UI-03 的隐藏清单基于 9.6.08 的 30 个 block code;9.6.13 首页出现了
    PAGE_RECOMMEND_SEARCH_TOP_BANNER / SEARCH_CHANNEL_ENTRY /
    MORE_RCMD 等新 code,需要在新版首页定制里勾选对应项才会隐藏。
  • 「我的页背景」清除后宿主侧 validType=4 注入不会回滚(与 2.4.2 一致),
    清除后如仍显示背景可重启网易云。

验证

  • :app:testDebugUnitTest:195 个用例通过(新增 MountResolver ClassLoader
    隔离、HookState entry/unavailable、UI-03 block 匹配、UI-05 过滤与
    Profile 门控、EN-01 调度点选择);:app:lintDebug 通过。
  • 9.6.13 挂载体检 145/145 OK;9.6.08 挂载体检 142/142 OK。
  • 真机 25102RKBEC:冷启动 runtime hooks installed: 4/4,UI-03 / UI-05 /
    EN-01 hook 链路全部命中,无 FATAL / ANR / hook failed。

2.4.3

Choose a tag to compare

@yigenhuobah yigenhuobah released this 25 Oct 09:45

修复

  • Issue #4:9.6.13 顶部频道管理(UI-04)不生效:网易云运行时使用 Tinker
    热修 ClassLoader,模块启动时挂载的是 base 副本,导致 UI-04 钩子全部
    “registered 但零命中”。现改为在首个 Activity#onCreate 用运行时
    ClassLoader 安装 UI-04 钩子,并补充 ArkFragmentV2 / arkview.ArkFragment
    数据链路覆盖。真机 9.6.13 验证:保留「心动/推荐」时顶部只剩这两个频道。
  • EN-01 9.6.13 入口适配(第一层):fullScreen 注入入口整包改名
    pc2.* → nb2.*,新增 BgInfoParser / BgStore 覆盖,避免 9.6.13 上
    EN-01 类定位失败。9.6.08 不受影响。

已知问题(本次未修复)

  • 9.6.13 上 UI-03 发现页推荐卡片隐藏仍不生效,首页卡片未按配置过滤。
  • 9.6.13 上 UI-05 底部导航保留仍不生效,底栏 tab 未按配置裁剪。
  • 9.6.13 上 EN-01 我的页自定义背景仍不显示:MyMusicProxyFragment
    类已消失(只剩 MyMusicFragmentV3/V4),页面架构变化,第二层调度点待
    重新逆向;9.6.08 不受影响。
  • 以上三项已记录,下一版继续处理;如急需可在 Issue 中补充诊断页截图和
    网易云版本号。

验证

  • :app:testDebugUnitTest:166 个用例通过;:app:lintDebug、
    :app:assembleRelease 通过。
  • 9.6.13 挂载体检 142/142 OK;真机 25102RKBEC 冷启动验证:保留
    「心动/推荐」时顶部只剩这两个频道,清空后恢复全部 6 个。

2.4.2

Choose a tag to compare

@yigenhuobah yigenhuobah released this 25 Oct 06:45

深度代码评审第三轮:调度/管线重构与热路径性能;附带 Issue #1 修复。

修复

  • 「我的」页自定义背景整页透出(Issue #1):根因是宿主 gd() 要求背景
    图经官方加载器真实加载完成才给内容区设半透明遮罩,模块贴图的本地路径
    走不通该链路。现于背景贴图后主动应用官方同款 scrim(0x1AFFFFFF),
    清除背景时回调宿主恢复;gd() 双签名兼容 9.6.08/9.6.13。已知限制:
    网易云 9.6.13 起「我的」页架构调整,EN-01 整条链待下一版适配
    (9.6.08 不受影响)。
  • 诊断回传改领先+尾沿调度并收敛为共享管线:TargetProcessPublisher 统一
    HookState 与 ExperimentState 两套回传(共享执行器/Context 反射缓存/authority),
    窗口内状态变化不再丢失,最后一次变化必随尾沿上报——冷启动后诊断页
    数分钟级延迟的问题根治;实验通道首事件改为立即发送。
  • AbTest 定位并入 HookKit 主管线(获得 Profile 参数消歧/旧名映射;DexKit
    兜底待锚点补充后自动生效);EN-01 全部类定位改走 HookKit,失败进入
    诊断页(原仅 logcat 可见)。

变更

  • HookKit 返回类型校验收紧:skipVoid 现要求精确 void 返回(全仓 26 个
    skipVoid 站点已逐一审计确认为 void 后收紧),9 个文件的逐处样板检查
    收敛为 installVoidByName/installConstFalse 中心助手。
  • 「我的」页 hook 的反射样板与 sampleSize 手工副本删除;set 型配置与
    强开映射解析收敛为 PrefsSetCodec/ForceMapCodec 单一实现;目标包名
    常量收敛到 Config.TARGET_PACKAGE。

性能

  • MMKV 读取 hook 零分配快路径:mmapID 按实例缓存(每读 1 次反射→0)、
    相关性判定改首字符预筛+regionMatches(最坏 240B/读分配→0)、黑名单为空
    时连查表都不进。基准前后对照见评审产物。
  • hit 限流键与 detail 解耦:被限流的命中不再拼字符串/进锁;限流表
    超 512 条自动清空重建,消除长会话无界增长。

验证

  • :app:testDebugUnitTest:165 个用例通过(2.4.1 为 140);两波七组经
    全站点审计门、补丁回放与基准复测验收;Issue #1 附带 3 个新用例。

2.4.1

Choose a tag to compare

@yigenhuobah yigenhuobah released this 24 Oct 09:41

深度代码评审第二轮修复(协议/并发/性能)。

修复

  • 回传协议边界真强制:StatusProvider 落盘前对两种通道按结构白名单整体校验
    (根键 / Feature 名 / 字段集 / 条数 ≤800 / 字符串 ≤256 / 总量 ≤64KB),不合拒绝;
    退役与真实协议脱节的 reg./hit./skip. 白名单死抽象。
  • 「我的」页背景三连修:external 共享副本写入改 tmp+rename 原子替换;
    clear()/syncExternal() 与导入共用单线程队列 FIFO 串行,消除「清除被在途
    导入撤销」「导入报成功但文件已清空」等交错终态;目标进程位图缓存按源文件
    指纹失效,换图/清除后即时生效,不再需要强杀网易云。
  • PV-03 启动任务黑名单套用核心任务保护名单(与 EX-02 共享同一来源),
    用户配错黑名单不会误杀受保护启动任务。
  • AbTest 挂载失败进入诊断页(原仅 logcat 可见);删除 EN-01 无消费死坐标。
  • JsonFilter 零删除快路径:延迟序列化 + 零删除原引用返回 + 嵌套串廉价预门;
    实测 500KB 零命中 18.8ms → 0.19ms(≈98×),过滤语义不变。
  • 死代码清理:VersionGate.shouldProceed(恒真)、DexKitAnchors.of、
    ProfileRegistry.clearActive、HookState.markNotFound 旧重载、
    MineBackgroundStore.calculateInSampleSize 包装。

变更

  • ExperimentFragment 改用 StatusProvider.readExperiments 单一读取入口。

验证

  • :app:testDebugUnitTest:140 个用例通过(2.4.0 为 123);七组修复经
    变异验证、补丁回放与独立基准复测验收。
  • 真机(网易云音乐 9.6.13 / versionCode 9006013,KernelSU + LSPosed,与第三方模块
    共存环境)冷启动验证:136 挂载全部注册、进程稳定无 FATAL、回传协议零拒绝。
    注:x86_64 模拟器上宿主防篡改库(libpoison.so)有启动崩溃复现,与本版改动的
    关联未证实(真机不重现),待模拟器环境恢复后复查。

2.4.0

Choose a tag to compare

@yigenhuobah yigenhuobah released this 23 Oct 19:53

底栏导航回归 + 适配网易云音乐 9.6.13(fail-open 版本门禁,versionCode 10)。

新增

  • 底栏 4 tab 导航:设置 / 实验 / 诊断 / 关于四个顶层 tab 常驻底栏,切换用
    hide/show 保留各 tab 滚动位置;「首页定制」保留为二级页(从设置页进入,
    带返回箭头,进入时隐藏底栏,返回后恢复)。首页定制页移除冗余的
    「仅本机可见」说明(功能表已有同一描述)。
  • 适配网易云音乐 9.6.13(versionCode 9006013):新增 Profile9613 挂载点总表,
    与 Profile9608 双档案并存,ProfileRegistry 按目标 versionCode 自动选择;
    相对 9.6.08 的混淆漂移共 34 个挂载点重定位(按 mount id 的 overrides 表 +
    hint 第三参等分片级差异),并新增 Profile 感知的方法名映射(hook 文件写死的
    9.6.08 混淆名按活动 Profile 换算成实际方法名)。9.6.08 仍受支持。
  • fail-open 版本门禁:未适配/未知版本不再因版本不匹配整体跳过 hook:
    active Profile 置空后回退硬编码挂载点 best-effort 安装(与 QuietBox 语义一致),
    状态卡/异常横幅提示未适配;移除 allow_unsupported_version 开关。

变更

  • 工程整备:新增 tools/release.sh(一键发版:预检 → 构建 → 校验 → 归档 →
    可选 tag / Release / 官方仓同步)、tools/verify-apk.sh(Xposed 元数据 / scope /
    R8 keep / Manifest / 版本号 / 签名证书校验)、tools/preflight.sh(JDK 21 + SDK +
    单测 + lint 预检)、CI(test + lint);接入 JaCoCo 覆盖率报告;新增 prefs/Feature
    一致性与 Hook 注册表等单测;appcompat 1.8.0 / material 1.14.0;构建基线 JDK 21
    (Java 字节码仍 17)。
  • 移除未使用的 compileOnly io.github.libxposed:annotation:1.0.0 依赖:
    全部源码零引用,compileOnly 不进入 APK,删除不影响功能与产物。
  • tools/check-mounts.sh 支持双档案:期望 versionCode 取自所选 profile JSON
    (9608 / 9613 各自携带),不再硬编码单一版本号。

修复

  • StatusProvider 上报 type 只认 mounts/experiments,未知 type 一律拒绝,
    防止绕过 mounts 通道的主进程门禁覆盖主进程快照。
  • EX-02 启动任务编排改用 installOne 传入的会话级 config 快照,不二次 Config.load。
  • ConfigStore 读取 Set 时空串视为未设置回退默认值,与 Config.loadSet 一致。
  • 主界面 tab 切换的刷新挂在事务 runOnCommit 之后,落在真正切到的新 tab 上。

验证

  • :app:testDebugUnitTest:123 个用例通过;:app:lintDebug、
    :app:assembleRelease、bash tools/preflight.sh、bash tools/verify-apk.sh 通过。
  • 模拟器(网易云 9.6.13 / versionCode 9006013)运行时:115 registered / 0 skip /
    10 mapped,无 FATAL。
    APK: cloudmusictool-2.4.0.apk
    versionCode: 10
    大小: 4,231,517 字节
    SHA-256: a378b3eeb5658f12d2d39efc3a1017ea926d345f33ddf865366bcdd27209e7de