# 开发、构建与发布说明 ## 目录 ```text projection-lab/ Android 应用,保留原包名 src/main/java/ UI、无障碍、显示宿主、本机无线连接 src/main/aidl/ 手机端助手 Binder 接口 src/main/assets/helpers/ 当前实机验证的两份 DEX src/main/assets/*.png 原创离线测试图及模糊层 tools/helpers/ 实时 GPU 渲染器、切屏控制器 Java 源码 tools/tests/ 原有纯 JVM 模型测试 tools/build_helpers.py 可跨平台重建 / 校验助手 tools/test_models.py 测试入口 tools/bake_demo.py 可选:重建编号测试素材 ``` 仓库从 TabFold 工作区抽出当前独立模块。未包含旧「折叠玻璃」应用、调试日志、手机截图、设备配对资料、本地 SDK、编译缓存或历史试验包。包名仍为 `io.github.sixzleo.tabfold.projection`,保留已安装版本的升级关系。 ## 构建 工具版本:JDK 17、Gradle 8.7、Android Gradle Plugin 8.6.1、SDK Platform 35、Build Tools 35.0.0。`minSdk=33`、`targetSdk=35`。Gradle Wrapper 校验分发包 SHA-256。 设置 `JAVA_HOME`、`ANDROID_HOME`。仅构建 APK 时,也可在不提交的 `local.properties` 中配置 `sdk.dir`。安装 SDK 后: ```sh python tools/test_models.py python tools/build_helpers.py --check ./gradlew :projection-lab:assembleDebug :projection-lab:lintDebug ``` Windows 使用 `gradlew.bat`。Python 脚本仅需 Python 3.10+ 标准库。`--check` 在临时构建目录编译助手并对比内置 DEX,不改资产;校验不一致时应先查明编译器或源码差异,不要跳过校验后宣称与测试版本相同。 修改助手后运行 `python tools/build_helpers.py`,它会生成并替换本仓库的两份内置 DEX,然后重建 APK。没有只提供二进制却缺少对应源码的助手。 编号素材已包含在仓库中,普通构建不需要重烘焙。若要修改测试图,可安装 NumPy / Pillow,为 `GLASS_DEMO_FONT` 指定本机合法可用的 TTF 字体,再运行 `python tools/bake_demo.py`。原图在 Windows Segoe UI 下生成,换字体会改变图案;项目不分发字体文件。 ## 已发布 v0.3.19 的二进制来源 v0.3.19 发布当前已安装、已验证的 debug APK,不重新签名。SHA-256: ```text dba73fd85c6295078f12234442aae5a6bc5581a87b9ad63339c5ce2801524297 GlassProjection-0.3.19.apk 1a86d91ce8ba6de667c24420b8ab5e6b773463285a2a0c9da1eafe7360179cc5 live.dex 2da8789e5157c684c6e4a594b673425411850e43c413df3be0a2a458fcbea470 controller.dex ``` `python tools/audit_publication.py --apk dist/GlassProjection-0.3.19.apk` 扫描待发布文件,并比较附件与本机构建的运行时代码、资源和清单。APK ZIP 时间戳、构建环境及签名密钥会影响整包字节;不承诺不同机器重建的 APK 与附件逐字节相同。私钥不纳入 Git。 早期 v0.3.12 Release 保持原样;v0.3.16 统一无障碍服务名称为「玻璃投影」,同步应用提示与使用教程;保留此前的全局范围、悬停恢复、真实手指滑动恢复及按钮反馈。详见[恢复选项](RESTORE-OPTIONS.zh-CN.md)。 ## 运行路径 v0.4.16 发布构建将版本元数据设为 `0.4.16` / code 73。与已安装验证的 code 72 比较,全部 31 个 DEX、assets 与资源表条目逐字节一致;签名证书与 GitHub v0.4.11 附件一致(证书 SHA-256 `0ae7bee46062ee4759414df5e96b68bf886761c26523a08a159aa6823dd7f651`)。重新通过模型、两份助手一致性、构建与 lint(0 错误、25 警告)。发布 APK SHA-256 为 `c0a985a2199aef24ce3192061cda45a84829774f3f3e6941545f91936641d908`,升级与适配范围见 [v0.4.16 更新说明](RELEASE-v0.4.16.md)。双屏实验、实机原始日志、配对身份和本机密钥不纳入本次提交或附件。 v0.4.16-flat-latch 按用户指定改为双条件锁定:厂商 `postureStatus=3` 与当前有效原始铰链读数 ≥175° 同时满足后才进入平展保护。提前收到 OPENED 时仍保持原角度映射及原有读数平滑,不再从约 160° 提前播放定时归位;锁定后忽略角度单独回落,只有有效姿态离开 OPENED 或物理接触闭合才解除/重置。`fullyOpened` 遥测现在表示已锁定的保护状态,原始厂商状态仍看 `postureStatus`;应用刚启动也遵守双条件,不因首个 OPENED 事件单独提前锁定。若锁定时渲染角度尚未跟到清晰端点,从上一渲染位置做 100 ms 快速残差归位,替代此前 300 ms 收尾。外屏与其他动画参数不变。 v0.4.16-flat-latch 已通过全套模型、助手一致性校验、构建与 lint(0 错误、25 警告),回归包含信号先到/角度先到、175°边界、重复提前 OPENED、启动与跨周期锁定、锁定后倾斜、真实折叠释放,以及姿态至渲染完整链路。已无线安装 code 72 并恢复原服务,确认首帧、`alive=true` 和 live helper SHA-256 `bd1e5688ef4ce9a9763144486bbcba0073ab9d2de0372c742a69777d2e7a761b`。实机多次记录 `posture=3 rawAngle=160 blocked=false`,随后 `rawAngle=175/176 blocked=true`,再次折叠 `posture=2 rawAngle=159 blocked=false`;一次锁定时助手渲染角度为 171.80914°,从该残差启动快速收尾。原参数保留,主观观感待用户反馈,未发布。 v0.4.15-flat-return 按用户指定将平展收尾从 240 ms 改为 300 ms,其他动画与倾斜保护不变。对应时序回归、全套模型、助手一致性、构建和 lint(0 错误、25 警告)通过。已无线覆盖安装 code 71、恢复原无障碍服务并确认内屏首帧和 `alive=true`;live helper SHA-256 为 `505e83b4290a36a022fb76c8f3442e678b2ef00d463f785064098ebfc634939e`,原参数保留,未发布。 v0.4.14-flat-return 按用户「收尾动画稍微慢一点」反馈,仅将共享平展归位时长从 180 ms 调为 240 ms;倾斜保护、反向处理、正常角度跟随及其他动画时长不变,实时与截图兼容路径共用新时长。更新对应时间点回归,全套模型、助手一致性、构建和 lint(0 错误、25 警告)通过。已安装 code 70,核对 live helper SHA-256 `bfcc3688d11edcde2baa3d5da9aceb7aec9247e798e0f8a3d79ae9fa1f94eed1`。安装后曾遇到系统 `attachAccessibilityOverlayToDisplay` 空执行器异常;仅重启本应用并重新绑定其无障碍服务后恢复,未改动挂载实现或其他服务。确认内屏首帧、`alive=true`、平展保护仍生效,用户参数保留;新速度观感待反馈,未发布。 v0.4.13-flat-return 修复上一版平展保护的动画收尾跳变:厂商姿态上报完全展开时,原始角度可能仍约 160°,直接阻止渲染会把当前变形画面瞬间清空。新增共享 `ProjectionAngleMotion`,仅对已有内屏画面从上一渲染角度开始做 180 ms 平滑归位;逻辑角度仍立即归为 180°,继续拦截倾斜误触发、悬停与切屏。平展期间不采用抖动的原始角度、不重启归位;反向折叠从当前画面恢复跟随,完全接触立即清除,新场景不继承旧尾帧。内屏入场门控采用平滑后的角度,避免先重置入场造成另一处跳变;已有悬停隐藏状态在平展归位期间保留,防止短暂重新出现。实时助手和截图兼容路径同步修改,外屏正常跟随参数不变。 v0.4.13-flat-return 已通过全套模型测试、两份助手源码一致性校验、APK 构建与 lint(0 错误、25 警告);新增回归覆盖连续几何归位、平展抖动、刷新间隔、反向、闭合优先与新场景。已正常停用旧服务、无线覆盖安装 code 69 并恢复原无障碍列表,确认自动重连、首帧及新 live helper SHA-256 `8297d2705729a57e280f199bc37eb9bd343ad5a7933e080ab3d9b44d95466f47`。用户原参数保留,收尾观感与平展倾斜复测待用户反馈;未发布。 v0.4.12-flat-guard 开发版修复内屏完全展开时倾斜整机误触发桌面动画。用户保持铰链完全展开并倾斜时,`TYPE_HINGE_ANGLE` 实测出现 166–179° 等读数,跨过原有 175° 动画边界;同期 lhasa 的 `fold_status.values[4]` 保持 3。用户真实合到约 150° 再展开时,该字段依次为 3 → 2 → 3,与系统原生 OPENED / HALF_OPENED 状态对应。`FoldPose` 在原 lhasa 适配范围内独立解析该字段:展开状态强制有效角度为 180° 并阻止投影,半展开立即恢复角度跟随;完全接触仍优先归为 0°。短事件、未知枚举和非有限值保留已知状态,其他机型保持原回退。`mirror-frame` 与 `desktop-telemetry` 增加 `postureStatus` / `fullyOpened`;实时助手沿用现有阻止投影、清除角度缓动和悬停状态的链路,截图兼容路径同步清除缓动。此前误改的参考预览已撤回。本字段是此次固件与实机动作验证的适配,不是通用物理平展协议;实际动画恢复时机仍取决于厂商姿态切换。模型回放覆盖误触发、真实合拢、闭合优先、无效事件、悬停与极端切屏阈值。 v0.4.12-flat-guard 已通过全套模型测试、两份助手源码一致性校验、APK 构建及 lint(0 错误、25 警告)。已正常停用旧服务、无线覆盖安装 code 68 并恢复原无障碍;助手自动重连并输出首帧。实机内屏倾斜时 `rawAngle=171`,但 `postureStatus=3`、`angle=180`、`projectionBlocked=true`,无悬停、渐暗或黑底。用户完成「平展倾斜 → 真正折叠 → 再展开」复测后反馈“正常”,确认本轮修复有效。用户原起始角度 6°、展开切屏 60°、合拢切屏 90°、模糊 50%、拉伸 100% 均保留。未发布到 GitHub。 v0.4.5–v0.4.7-wireless-setup 开发版集成本机无线 ADB:保存应用私有配对身份,用本机 mDNS 自动发现配对及连接端口,以回环地址完成连接;通过已安装 APK 中的 StandaloneHelper 接回原 IHelperHost Binder、启动相同的两份 DEX。助手不依赖 Shizuku 进程,Shizuku 作为备用方式保留。界面顺序改为「连接助手 → 开启无障碍」,连接准备可以在无障碍开启前完成。小米通知无法输入、悬浮控件在开发者设置不可见后,v0.4.7 将默认入口改为普通 Activity 的系统小窗,不依赖通知或悬浮权限;没有启用分屏。已构建、安装并恢复原无障碍状态,实机外屏确认配对 freeform 窗口在开发者设置上保持可见。首次配对、独立助手启动及暂停/重连的完整验证待完成,当前未发布。交互和限制见 [本机无线启动](WIRELESS-SETUP.zh-CN.md)。 v0.4.4-onset-composite 修正用户在关闭模糊后定位的起步重影:原逻辑用 `endpoint * entry` 降低动画层透明度,同时已经偏移采样位置,导致原位桌面和偏移图标同时可见。改为活动画面不透明接入,将起步进度用于倾角、裁切和由倾角产生的模糊;初始中性帧直接采样清晰源,避免纸张边缘先行变暗。实时与兼容路径同步修改;切屏布局等待仍受黑底就绪门控,内屏静止半侧的空间羽化及悬停末段恢复沿用已有行为。模型覆盖中性首帧、原位图标贡献为零、端点交还及内外两侧起步;构建和 lint 通过(0 错误、13 警告)。已安装 code 59 并核对新 helper 哈希;实机外屏 2°、模糊关闭时捕获的活动区域全部不透明,半透明像素为 0,画布外透明区域正常。抓帧会阻塞本次呈现,抓帧日志中的 631 ms 首帧耗时不用于评估正常启动性能。用户实机反馈“确实消失了”,确认本轮起步重影与跳变修复有效;未发布。 v0.4.3-small-angle 将同样的起步插值接入内屏:实时 GPU 和兼容渲染路径显式传入当前屏幕,内屏以 `180 - angle` 判断起步范围。内屏 176–171° 对应外屏 4–9°,沿用 72 ms 时间常数及两端平滑衔接;离开起步区后恢复原响应。外屏参数不变,旧三参数入口保留外屏语义。测试覆盖全角度内外对称、内屏 120 Hz 节奏、收敛、反向和正常角度速度;构建及 lint 通过(0 错误、13 警告)。已安装 code 58、恢复服务并核对新 helper 哈希和首帧,用户模糊及拉伸设置保留,内屏实际观感待反馈,未发布。 v0.4.2-small-angle 根据用户确认的 4° 首次可见、9° 开始顺滑区间,进一步加密 4–9° 的插值,跟随时间常数为 72 ms;2–4° 平滑进入,9–14° 平滑退出额外平滑,14° 以上恢复原 12 ms 响应。在固定 1° 台阶、120 Hz 帧节奏下,首帧约推进 11%,12 帧(100 ms)约完成 75%,216 ms 内达到约 95%;这是按经过时间计算的插值,不排队播放帧,反向立即跟随,实际呈现帧数仍取决于渲染调度。渲染层已有 120 Hz 请求,设备系统记录也为 120 Hz,未将其视为实测 GPU 帧率。模型测试覆盖 8/8/9 ms 节奏、反向、收敛及边界连续性;构建和 lint 通过(0 错误、13 警告)。已正常停用旧服务、安装 code 57 并恢复服务,确认新 helper 哈希及首帧;保留用户模糊和拉伸设置,未发布,4–9° 顺滑与滞后观感待反馈。 v0.4.1-small-angle 开发版加强 0–10° 整数铰链读数之间的时间插值:跟随时间常数从 12 ms 调至 24 ms,16 ms 首帧推进约 49%,让后续帧承接剩余角度;10–14° 用 smoothstep 平滑回到 12 ms,14° 以上沿用原响应。使用目标角度决定时间常数,固定目标下按实际经过时间插值,60/120 Hz 结果一致;不改变角度对应的模糊、裁切及切屏阈值,物理闭合仍立即清除。模型测试覆盖逐整数开合、72 ms 内约 95% 收敛、反向无越界及 10° 边界连续性。APK 构建和 lint 通过(0 错误、13 警告);正常停用旧服务后安装,确认新 live.dex 哈希与 GPU 首帧,恢复原启用状态,未发布到 GitHub,观感待用户反馈。 v0.4.0 在 v0.3.43 开发验证的基础上统一内外屏预淡出和切屏后淡入:实际切屏阈值保持设置值,接近目标角度前 12° 按 smoothstep 渐暗;切屏时保持全黑,待几何和新源帧就绪后 180 ms 渐亮。渐变在动画输出层内合成整屏(包含内屏原本透明的清晰半侧),黑底继续位于其下,不以撤层实现画面交接。内屏采用 120 ms 的稳定/新帧窗口,外屏保留至少 450 ms 防迟到布局;未就绪等待 900 ms 后渐亮兜底。反向开合和悬停取消预淡出,跟随同样的 3° 方向确认规则。渐亮/取消的进度按 GPU 当前时间插值;10°/170° 等极端设置会缩短提前角度区间,避免完全闭合/平展时预先变黑。模型覆盖内外双向、阈值不变(与原切屏控制模型对照)、反向/悬停、慢速手势和未切屏超时,构建与 lint 通过。已安装并确认新 DEX 和 GPU 首帧;控制器 DEX 保持原哈希。实机展开 49°、合拢 130–131° 开始渐暗,均早于切屏;内容就绪后约 180–189 ms 结束渐亮和黑底覆盖。 v0.3.42 开发版按用户纠正改为两层结构:系统原屏之上为黑底,动画层位于黑底之上;黑底相对动画 Surface 的层级固定为 -1。布局未稳定时动画层透明,只露出黑底;内容就绪后直接在黑底上绘制动画,就绪回执仅结束布局等待,不改变黑底可见性,因此不会因动画提交和撤罩时序不同而露出原屏。黑底保留到正常闭合/悬停恢复、切回内屏或离开生效范围;未就绪仍有 900 ms 超时退出。模型测试覆盖就绪后延迟帧仍有黑底、等待超时与已就绪状态分离、闭合恢复和反向取消;构建、lint 通过,已安装并核对新 DEX 与首帧。SurfaceFlinger 确认黑底存在且镜像克隆因 eLayerSkipScreenshot 不可见;实机 COVER_CONTENT_READY 后 coverBacking=true,切回内屏时才出现 COVER_BLACK false,验证无撤罩交接。 v0.3.41 开发版按用户要求用独立纯黑遮罩遮住合拢切入外屏时的布局重排。遮罩是现有显示根层的子层,由服务在屏幕类型切换时显示,助手在启用前将其排除于镜像采样。布局就绪判据为切换至少 450 ms、ON 状态下有效尺寸和方向稳定 120 ms、至少两帧新源画面;这是布局稳定的启发式判断,不是系统桌面完成信号。助手先提交当前动画帧,再以切换 token 和几何签名通知服务揭开遮罩;旧回执、反向展开和熄屏均不会遗留黑层,独立服务计时在 900 ms 兜底退出。模型测试、构建和 lint 通过;已安装并确认新 DEX 和 GPU 首帧。实机多次记录 COVER_BLACK true 先于外屏 ON,COVER_FRAME_READY 后 COVER_READY 在 457–562 ms 撤罩,迟到旋转也由遮罩覆盖;该证据验证遮罩时序,最终视觉完整性仍待用户确认。 v0.3.40 开发版进一步缩短外屏切入空档:屏幕类型切到外屏后 500 ms 内,后续尺寸和旋转更新沿用该次切屏起点,避免重新计时;外屏场景切入使用 80 ms 过渡。正常合拢后开始展开仍从零进行 180 ms 平滑入场,内屏计时保持 v0.3.39 行为。新增分阶段慢调用日志,区分遥测、源帧获取和模糊金字塔准备。回放覆盖屏幕类型先变、51 ms 后尺寸更新、迟到旋转、独立旋转、正常展开时长及内屏计时不变;模型、构建和 lint 通过,已安装并核对新 DEX、版本及 GPU 首帧。实机外屏尺寸更新时已推进到 75%–93%,一次点亮首帧 sceneAgeMs=80、amount=1.0;迟到旋转 sceneAgeMs=435 也维持 1.0,确认没有重新露出中性入场帧。仍记录到尺寸/方向交接的帧间空档,实际观感待用户确认。 v0.3.39 开发版优化切屏亮起后的原屏空档:入场场景只包含屏幕尺寸、旋转与内外屏,不再把 OFF/ON 状态计为新场景。服务在显示几何变化时记录单调时间,GPU 新场景的首帧按已过去的时间推进 180 ms 入场,避免显示提交等待结束后再次从零起步;正常合拢后展开和平展后合拢仍从零平滑开始。增加切屏首帧场景年龄、入场进度和超过 40 ms 的提交耗时日志,便于区分应用入场等待与系统提交阻塞。回放覆盖 370 ms 渲染停顿、同屏 OFF/ON、延迟首帧、闭合后重新起步及异常未来时间;模型、构建、lint 通过,已安装并确认新 DEX 与 GPU 首帧。实机多次切屏的 ON 状态后直接 ENTRY_COMPLETE,没有再次 NEUTRAL_ENTRY;一次延迟几何首帧 sceneAgeMs=266、amount=1.0,验证已接续进度。尚未定位剩余帧间停顿的具体调用,不将其全部归因于 eglSwapBuffers,也不宣称已消除所有原屏空档。 v0.3.38 开发版小幅延长内屏跨轴模糊的收尾:最大延伸系数从单叶宽度的 18% 调到 22%,仍乘 sin(倾斜角) 随合拢增长。距离场和渐隐共用加宽后的范围,让接收半屏用更长距离承接模糊;远侧最大距离、接收侧内容坐标及外屏 v0.3.37 效果保持原样。模型测试、构建和 lint 通过,已安装并核对新 DEX、版本及 GPU 首帧,待用户确认实际衔接观感。 v0.3.37 开发版修复外屏中轴线中段的清晰斑块:原轴线处景深距离为零,而上下边角额外散射形成了围绕清晰中心的虚化。现在外屏模糊采样使用连续的虚拟距离场,近轴端为单叶宽度的 18%,远端仍为完整叶宽;实际景深随渲染倾角从零平滑增加,覆盖整条轴线。距离场不改变纸张轮廓和内容坐标,保留远侧最大模糊及内屏跨轴过渡。实时 GPU、截图和预览路径同步。模型测试、构建和 lint 通过,已安装并核对新 DEX 与 GPU 首帧;模糊强度与拉伸设置保持 100%。用户实机反馈“现在我满意了”。 v0.3.36 开发版按用户纠正改变中轴线过渡方向:保留活动半叶的覆盖,取消中轴线处的硬裁切,让模糊延伸到另一半屏幕后再淡出。延伸宽度为单叶宽度的 18% 乘 sin(倾斜角),随内屏合拢逐渐增加,平展时归零;接收半叶只模糊原位置内容,横向坐标不变。模糊距离的清晰终点平移到延伸区末端,按全叶宽度归一化保证远侧最大距离不变;中轴线两侧共享连续距离场,渐隐只发生在另一半屏幕。恢复活动半叶的边缘散射和纸张轮廓,实时及截图输出均允许跨轴绘制。新增角度范围、跨轴连续性、活动侧完整覆盖、接收侧坐标固定及尾端归零检查,模型测试、构建、lint 通过。已安装并确认新 DEX、GPU 首帧及原模糊/拉伸设置保留。已抓到有效内屏 GPU 帧:中轴线 x=591 像素处 alpha=255,接收侧约 39 像素内依次降至 246/219/133/44/0,验证覆盖确实跨轴并在另一半淡出。 v0.3.35 开发版根据实机反馈取消 v0.3.34 的 22% 区间二次虚化衰减:它把模糊和透明度集中在同一区间,观感上出现新的模糊起始带。改为保留原始距离虚化,附加边缘散射在整个半叶范围内按距中轴线的距离从零线性增加;纸张暗边也在整个半叶范围内渐变。横向采样恢复原有线性角度映射。仅中轴线附近 4% 半叶宽度用于叠加层交回原生像素,不再用该区间调制模糊半径。外屏及远侧最大模糊保持原设置。全叶散射连续性、配置边界、起步及物理闭合模型通过,构建和 lint 通过;已安装并确认新 DEX 和 GPU 首帧。 v0.3.34 开发版修复内屏中轴线清晰衔接:在活动半叶靠中轴线的 22% 宽度内,以 smoothstep 同步将模糊半径、纸张暗边和横向偏移收回;叠加层透明度同时归零,准确露出系统原生清晰画面,消除另一半屏幕边界的硬切。模糊半径在最终限幅后再乘过渡权重,强模糊也必须在中轴线归零。远侧及外屏效果保持不变。截图渲染共用透明衔接,编号预览在相同区间混入原始清晰图。新增连续性、高强度归零、近轴坐标对齐及远侧不变检查,模型、构建和 lint 通过,已安装并确认新 DEX 与 GPU 首帧。 v0.3.33 开发版新增「视差形变 → 拉伸与裁切强度」设置,范围 0–125%、步长 5%,默认 100% 保持当前线性效果(30° 裁切 12%)。0% 取消横向拉伸裁切,纸张轮廓和虚化独立保留;强度写入 stretch_percent,旧配置缺省为 100%,恢复默认同步还原。实时 helper、截图路径及编号预览均使用同一数值,内外屏共享,修改立即传到 mirror-frame。配置上下界保证采样顺序不反转。模型覆盖默认一致性、零/半/满/最大值、内外屏锚点与最大形变边界;构建、lint 通过。已安装,实机验证减号 100%→95%、实时参数及 SharedPreferences 落盘,界面检查通过,结束时读到当前值 100%。 v0.3.32 开发版修复外屏起步的目标位置接入:新增共享 ProjectionEntrance,每次从不可见进入动画或切换输出场景时,从零偏移开始,用 180 ms 同步接入裁切、纸张形变及透明度。避免原先已带当前角度偏移的图像直接淡入;接入结束后保持 v0.3.31 的线性裁切(30° 为 12%)。物理合拢、退回起始阈值后立即复位,再次展开重新接入。新增首个读数跳至 2°/16°/30°、中断重开、帧率独立及场景重建检查,模型测试、构建和 lint 通过。已安装,确认新 DEX 加载、GPU 首帧及真实开合 NEUTRAL_ENTRY / ENTRY_COMPLETE 日志;补充验证内屏从完全展开开始合拢(首个角度 174°/165°)、117° 屏幕交接、回到平展后重开及物理合拢复位,均通过;0.3.32 已共用该逻辑,无需另装。主观跳位感待用户确认。 v0.3.31 开发版提供线性裁切试用:裁切比例为倾斜角度乘 0.004,10°/20°/30°/60° 分别为 4%/8%/12%/24%,沿用 85° 倾斜上限(最大 34%)。采样坐标改为 x*(1-crop*abs(x)/leafWidth),使远侧及内部各点的采样位移均与角度线性对应,同时保持中轴线锚定。裁切使用独立 uniform,绕开纸张起步的非线性几何缓入;透明度缓入、纸张虚化、角度平滑及悬停恢复保留。新增逐角度和内部点等增量检查,模型测试、构建及 lint 通过;已安装并确认新 DEX 与 GPU 首帧,线性手感待用户确认。 v0.3.30 开发版将 30° 远侧裁切量校准为 12%,仅将裁切响应角从 55° 调为约 32.7375428°,保持 0.24 增益上限、零斜率起步和 8° 同步缓入。模型测试校验 30° 的 12% 目标及起步连续性,构建、lint 通过,已安装并确认新版 DEX 加载与 GPU 首帧。 v0.3.29 开发版放缓起步及裁切:透明度与形变统一使用平滑后的角度,起始阈值之后以 8° smoothstep 同步从中性平面缓入;物理合拢仍立即清除。裁切增益改为 0.24*(1-exp(-(tilt/55°)^2)),起点斜率为零,15° 裁切约 1.7%、30° 约 5.8%、60° 约 14%,最大约 18%;保留中轴线锚点和上下纸张虚化。新增起步连续性、柔和端点、首度增量及合拢清除检查,所有模型测试、构建、lint 通过。已安装测试设备,确认新 DEX 与 GPU 首帧,动态观感待用户确认。 v0.3.28 开发版按最新反馈改为中轴线锚定的单侧透视裁切:外屏保留左侧锚点,内屏活动半叶保留右侧铰链锚点;源坐标按 x/(1+gain*abs(x)/leafWidth) 映射,gain=0.45*(1-exp(-tilt/28°))。远侧源内容在 15° 时裁去约 16%、30° 时约 23%,最大约 30%,输出仍覆盖屏幕宽度;中轴线附近形变较小,纵向保持不变。保留上下纸张轮廓、连续虚化及侧边颜色延展。模型测试、构建和 lint 通过;安装后首次挂载遭遇系统 AccessibilityInteractionClient 空 Executor 异常,仅重连本应用无障碍服务后恢复,确认新版 DEX 加载及 GPU 首帧,动态观感待确认。 v0.3.27 开发版将两侧端点同时固定,取消远侧裁切;内部使用两端位移为零的平滑横向映射,最大位移为单叶宽度的 2%,采样映射的局部横向比例限制在 0.92–1.08,纵向比例保持不变。纸张轮廓只在上下退缩,并以圆角接到左右屏幕边界;沿用统一距离场扩散。实时高斯预滤波先按屏幕旋转方向延展左右源颜色,避免黑色填充被卷入侧边;截图缓存及编号演示素材同步处理。几何和状态模型测试、Debug 构建及 lint 通过,已安装到测试设备,确认加载新 DEX 并输出首帧;截取约 35.5° 外屏动画 GPU 帧,确认左右中段无退缩黑缝、上下纸张边界保留。动态开合手感及内屏观感待用户确认。 v0.3.26 开发版统一边缘扩散:移除 side / vertical / corner / far 四种区域增益组合,整个圆角轮廓共享同一个距离场。边缘散射按到轮廓的距离以高斯权重向内容内部过渡,与距离模糊通过方差相加合成;纸张羽化宽度使用同一散射半径,避免角落与相邻边各自增强造成局部浓淡突变。保留圆角、远侧较重的距离虚化、固定边裁切及 12 ms 跟随。构建与 lint 通过,已安装待观感确认。 v0.3.25 开发版为纸张遮罩加入圆角距离场,圆角半径随开合增长,平整时归零。靠近边角与远侧裁切边界时额外提高局部模糊半径,并扩大向黑底扩散的过渡区;实时采样半径限制在内置模糊金字塔支持范围内。外屏左对齐裁右、内屏右对齐裁左,以及原内容 UV 均保持。GLSL 与 AGSL 同步,构建、lint 与助手一致性检查通过。 v0.3.24 开发版修正裁切基准:内容采用原始 UV 等比例采样,取消将外屏左侧/内屏靠铰链内容移出视口的纹理平移。外屏左对齐裁右侧,内屏运动的左半面靠铰链右对齐裁左侧;视差保留 8% 单叶宽度的最大变化,转移到远侧纸张裁切边界,叠加原纸张透视轮廓和柔化黑边。保留 12 ms 跟随及增强虚化。模型测试检查固定边坐标、相反裁切方向和内容比例,Android 构建及 lint 通过。 v0.3.23 开发版将视差位移幅度从单叶宽度的 3.5% 提升到 8%,保留纸张轮廓与模糊参数。实时和兼容路径共用 `ProjectionMath.followAngle`,指数平滑时间常数从 28 ms 降至 12 ms,缩短开合及反向跟随滞后;模型测试验证 36 ms 内达到阶跃目标的 95%、帧率独立性及反向不越界。原始铰链角度仍一比一驱动纸张倾角,不使用角度预测;接触闭合继续立即清零。 v0.3.22 开发版进一步增强纸张远侧虚化:实时渲染的距离增益由内屏 0.25 / 外屏 0.35 调为 0.55 / 0.75,半径上限由 0.012 提至 0.03;移除内屏边缘的 0.65 倍减弱模糊,纸张边缘柔化半宽统一使用 2.4 倍 sigma。保留近侧零距离清晰端、纸张轮廓、等比例内容以及用户保存的模糊强度,AGSL 预览同步加强模糊。 v0.3.21 开发版将纸张轮廓与桌面内容分开计算:纸张轮廓保留原参考平面的透视交点,超出纸张的部分显示黑色,并按模糊半径柔化边界;内部内容只使用横向视差偏移,最大为单叶宽度的 3.5%,纵向坐标不变,避免图标文字被透视坐标拉长。模糊仍随原模型的射线距离渐进增加,保留近清远糊的玻璃效果。实时 GLSL、AGSL 预览及 JVM 数学模型同步;内屏右半面保持原画面。模型测试同时检查内容宽高不变、折叠后的纸张远角露出黑底。开发版已安装,约 37° 的实机 GPU 帧确认纸张黑边、近清远糊与等比例内容同时存在;模型测试、助手一致性检查、Android 构建和 lint 通过,最终观感待用户确认。此实现是针对手机观感的调整,不声称与 Blender 参考项目的真实相机射线模型等价。以上 v0.3.19 哈希仅对应已发布附件。 v0.3.19 修正 v0.3.17 对粗粒度 `foldStatus` 的解释:测试设备 `Build.DEVICE=lhasa` 在已打开一条缝、铰链约 15–19° 时仍报告首值 1(系统 CLOSED);此前保护错误屏蔽了这段真实开合。经用户配合执行「小角度展开 → 完全合拢并倾斜 → 打开一条缝」,同一 `fold_status` 事件的 `values[2]` 依次为 1 → 0 → 1,实测可用于接触分离判断。`FoldPose` 仅在该机型和已匹配传感器上解码至少 11 项的事件,`contactStatus=0` 阻止投影、`1` 恢复原始角度;此字段是基于实机采集的适配,不是已获得厂商文档保证的通用协议。其他机型不读取该字段;缺少首个有效接触状态时使用原粗状态,后续短事件/无效值保留已知接触状态。两种 telemetry 均附带 `contactStatus`(-2 未适配、-1 未收到有效值)。新增测试回放这次误拦截和合拢倾斜数据。 v0.3.19 已安装实测:原始 2°/4° 且接触分离时允许投影;接触闭合、原始角度漂至 12° 时有效角度仍为 0°。用户确认小角度动画恢复、合拢倾斜无模糊。模型测试、Android 构建和 lint 通过。 动画设置包含 `start_angle` 偏好,默认 1°、范围 1–30°;`mirror-frame` 与 `desktop-telemetry` 以 `startAngle` 传递。应用与实时助手共用 `ProjectionMath.endpointOpacity`,起点后 5° 内渐入;若切到内屏时还处于该范围,内屏也遵守这段渐入,避免提前切屏绕过设定起点。物理闭合门控始终优先。`FoldHoldGate` 使用相同起点,使低角度动画仍可悬停/滑动恢复;切屏控制器的方向判断保持独立。修改设置无需重启助手,恢复默认会还原起点。 `ProjectionService` 负责作用范围判断、铰链数据、实时输出宿主和助手心跳。v0.4.11 默认由本机无线 ADB 启动 StandaloneHelper,经受限 provider 接回 MobileHelper;MobileHelperHost 以 shell UID 启动 APK 内置的两份 DEX,并检查它们是否存活。旧 Shizuku UserService 兼容路径保留在代码中。 v0.3.17 增加物理闭合门控:在已验证的小米固件上订阅 `xiaomi.sensor.fold_status` / `fold_status FOLD_STATUS Wakeup`,其首值 `1` 表示系统闭合范围,`0` 表示系统打开范围;这不等于两半机身是否完全接触,lhasa 的最终投影门控按上文接触状态处理。完全合拢时倾斜整机,`TYPE_HINGE_ANGLE` 曾实测跳到约 30°,所以不能只靠角度阈值判断闭合。物理闭合(或等待该传感器首个有效事件)期间,对渲染器和切屏控制器提供 0°,并显式禁止投影;渲染器同时清除缓动和悬停回放状态。打开后恢复原始角度跟随。传感器不可用时保留原有角度路径,不把其他机型的任意厂商传感器当作相同协议。 `mirror-frame` / `desktop-telemetry` 的 `rawAngle` 保留原始角度,`angle` 为门控后的角度,`projectionBlocked` 表示禁止投影;`foldStatus` 为 `-2`(无可用传感器)、`-1`(等待首个事件)、`0`(打开)或 `1`(闭合)。无效事件不会解除已有的闭合状态。升级同步增加 Shizuku UserService 版本,使常驻助手加载新的内置 DEX。 显示器级挂载在当前固件上可能在应用进程被升级终止后残留最后一帧。`mirror-lease` 现在同时交付本应用的根图层句柄和所属进程 Binder;渲染助手的 `OutputOwnerGuard` 在进程死亡时隐藏并解除该根图层挂载,退出时也执行清理。渲染循环退出前提交透明帧。开发安装应先正常停用本服务,再覆盖安装并恢复原启用状态;旧版已经失去句柄的残留图层不属于新进程的 lease。 `LiveMirrorWindowProbe` 取得实时镜像,将它送入 GPU 模糊金字塔,再按铰链角度投影。当前默认路径不按每个桌面页做静态截图缓存。`MirrorPreview` 通过 `SurfaceControlViewHost` 和显示器级无障碍挂载提供输出,避开此前窗口层级参与的部分系统淡入动画。输出不接收触控。滑动恢复由 TouchObservation 为本服务配置被动观察,FingerSwipeGate 判断位移;FoldHoldGate 统一管理悬停和滑动恢复状态,渲染器中的 FoldReturnMotion 平滑回放投影。 `EarlyDisplayHelper` 从受 UID 限制的 provider 读取状态,以进程绑定的 DeviceStateRequest 控制切屏。心跳过期、场景不允许或进程退出时释放覆盖;用户暂停会停用无障碍并停止助手。 v0.4.8 在连接助手卡片与配对小窗补充开发者选项引导:小米「设置 → 我的设备 → 连续点击 OS 版本」,并提供打开系统设置按钮。首次配对检查开发者选项是否开启,未开启时先展示说明。构建与 lint 通过,覆盖安装后实机确认主页面说明、帮助弹窗和设置按钮可见。 v0.4.9 修复本机 ADB 配对后启动失败:保留 legacy shell 启动流至独立助手 Binder 握手完成,使用 `setsid -w nohup` 分离助手会话后再断开 ADB。实机由应用自动认证、约 1.5 秒接回助手,并启动渲染与切屏 DEX;ADB 启动会话关闭后进程继续存活。启动阶段和独立宿主失败原因写入诊断日志,不记录配对码。早期版本关于独立启动尚未验证的记录由此补充,仍不代表全部首次授权及重启场景已验证。 v0.4.10 将小窗和连接失败提示中的「打开无线调试」统一为直达入口。测试机的通用无线调试 action 不存在,设置 APK 的导出 SubSettings 接受 AdbWirelessDebuggingFragment 参数。覆盖安装后从应用按钮实测,设置任务 launchedFromUid 为本应用 UID,无线调试页与配对小窗同时可见;不使用 shell/Shizuku 代开页面。保留开发者选项备用入口和未开启时的帮助引导,构建及 lint 通过。 v0.4.11 将连接区收敛为一个「配对」按钮,移除自动连接按钮、重复配对按钮及 Shizuku 备用入口。助手已连接时提示无需重复配对;仅有本地记录时先验证连接,系统明确要求配对时清除旧标记并进入小窗流程,网络失败不清除记录。实机遇到 AdbPairingRequiredException 后确认 paired 标记变为 false,并进入由本应用 UID 启动的配对小窗和无线调试页。构建及 lint 通过(0 错误、25 警告)。 ## 设备适配边界 `lhasa` 的接触状态适配要求物理闭合传感器可用。传感器未匹配、注册失败或访问被拒绝时,`foldStatus=-2`、有效 `angle=0`、`projectionBlocked=true`;原始 `rawAngle` 仍用于诊断。恢复传感器后需重连无障碍服务并等待首个有效状态,才允许动画。未适配接触状态的其他机型保留原有角度回退。发布与升级说明见 [v0.4.17](RELEASE-v0.4.17.md)。 当前固件的状态编号 `0` 对应外屏、`2` 对应内屏;输出采用 1182 × 1182 缓冲与 2 倍缩放,逻辑画布覆盖 2364 × 2364。内屏常用逻辑尺寸 2364 × 1672,外屏 1168 × 1712。方向映射、屏幕识别及这些假设分布于 MirrorPreview、ProjectionService、实时渲染器和 EarlyDisplayModel。 这些不是 Android 各厂商通用约定。适配新设备时需先核对传感器、显示布局、系统状态、隐藏 API 权限和坐标,再调整实现。不要把 `minSdk` 当作兼容清单。项目没有使用 root,也没有修改系统框架或刷机。 ## 权限与诊断 Provider 仅允许本应用 UID 或 shell UID 2000 调用。无线 ADB 只执行固定 APK 入口;宿主只启动内置且设为只读的 DEX,不接受任意命令。两条宿主路径都要求 shell 身份,不使用 root。无线调试配对身份在应用私有目录内生成,不能提交到仓库。 兼容截图代码与少量诊断入口仍随当前 APK 保留。CacheProbeActivity 只处理内置编号图。实时助手在开发者主动请求 GPU 导出、或手动启动限时预览模式时,可把一帧画面写入 `/data/local/tmp/tabfold-live-projection.png`;正常桌面模式不主动启用这些导出。调试时应自行检查日志/图片并脱敏,不能直接上传用户桌面、锁屏通知等内容。 普通 `uiautomator dump` 会建立 UI 自动化会话,可能暂时抑制普通无障碍服务,导致本应用销毁、重连。验证后台常驻时不要同时执行它;优先读取 dumpsys、受限 provider 状态和必要的截图。 ## 已完成的验证 - Android debug 构建与 lint。 - 几何、中轴锚定、场景门控、开合方向与角度模型测试。 - 测试设备上的桌面/锁屏、内外屏投影与自定义切屏。 - Shizuku 手机端启动助手,退出设置页后继续运行。 - 单独终止渲染子进程后,手机端助手自动重启并恢复画面。 - 配置小米后台保护后执行一次一键清理,无障碍和原进程保持运行,用户确认动画仍在。 这些记录不代表所有设备适配、长期后台稳定性或持续 120 fps 的保证。