# DevicePlugin 阶段二任务分解文档 — ScreenPlugin 功能迁移 ## 项目背景 根据 CEO 陈逸飞指示,DevicePlugin 阶段一(基础框架)已完成并通过 73/73 测试。现进入阶段二:将 ScreenPlugin 的核心功能迁移到 DevicePlugin,实现统一设备管理架构。 ## 阶段一成果回顾 - ✅ Message enum 扩展(DeviceCommand/DeviceResponse/DeviceEvent) - ✅ DevicePlugin 骨架与 Backend trait 定义 - ✅ LinuxArm64Backend 实现(Display + SleepInhibit + Backlight) - ✅ 单元测试与文档完善(73/73 测试通过) ## 阶段二总体目标 1. 将 ScreenPlugin 的 systemd-inhibit(防息屏)和 unclutter(光标隐藏)功能迁移到 DevicePlugin 2. ScreenPlugin 改为通过 DeviceCommand 调用 DevicePlugin(thin wrapper) 3. 确保现有功能不丢失,保持向后兼容 4. 为未来完全移除 ScreenPlugin 做准备 ## 当前状态分析 ### ScreenPlugin 现有功能(src/plugins/screen/mod.rs) 1. **防息屏(systemd-inhibit)**: - `start_wake_lock()` — 启动 systemd-inhibit 子进程(已在 DevicePlugin 实现) - `stop_wake_lock()` — 停止 systemd-inhibit 子进程(已在 DevicePlugin 实现) - 处理 `Message::ScreenLockRequest(bool)` 消息 2. **光标隐藏(unclutter)**: - `set_cursor_hidden(bool)` — 启动/停止 unclutter 进程(**需要迁移**) - 处理 `Message::CursorVisibility(bool)` 消息 3. **配置驱动**: - 从 `ctx.config.display.prevent_screen_lock` 读取配置 - 在 `start()` 时自动启动防息屏和隐藏光标 ### DevicePlugin 现有能力(src/plugins/device/linux_arm64.rs) - ✅ `SetSleepInhibit(bool)` — 已实现 systemd-inhibit - ✅ `SetBacklight(bool)` — 已实现背光控制 - ✅ `GetDisplayInfo` — 已实现显示信息查询 - ❌ **光标隐藏功能缺失** — 需要新增 ## 任务列表与执行顺序 --- ### Task 1: DeviceCommand 扩展 — 添加光标控制命令 **负责人建议**: 张明远(内核工程师,负责阶段一 Message enum 扩展) **优先级**: P0(阻塞后续所有任务) **输入文件**: - `src/core/message.rs` — 现有 DeviceCommand 定义 - `src/plugins/screen/mod.rs` — ScreenPlugin 光标隐藏实现(参考) **任务描述**: 1. 在 `DeviceCommand` enum 中添加新变体: ```rust /// 设置光标可见性 /// - true: 显示光标 /// - false: 隐藏光标(通过 unclutter 或平台特定方式) SetCursorVisible(bool), ``` 2. 在 `DeviceCapability` enum 中添加新能力: ```rust /// 光标控制能力 Cursor, ``` 3. 确保新变体派生 `Debug, Clone, Serialize, Deserialize` 4. 添加文档注释说明用途和平台差异 **输出文件**: - `src/core/message.rs` — 更新后的消息定义 **验收标准**: - [ ] `cargo check --workspace` 零 warning - [ ] `SetCursorVisible` 变体正确派生 serde traits - [ ] 文档注释清晰说明 Linux/Android/Embedded 平台的实现差异 - [ ] `DeviceCapability::Cursor` 已添加 **预计工时**: 0.5 小时 --- ### Task 2: LinuxArm64Backend 扩展 — 实现光标控制 **负责人建议**: 赵雨薇(屏幕工程师,ScreenPlugin 原作者,熟悉 unclutter) **优先级**: P0(依赖 Task 1) **依赖**: Task 1 必须完成(DeviceCommand 已扩展) **输入文件**: - `src/plugins/device/linux_arm64.rs` — 现有 Backend 实现 - `src/plugins/screen/mod.rs` — ScreenPlugin 光标隐藏实现(参考 set_cursor_hidden) **任务描述**: 1. 在 `LinuxArm64Backend` 结构体中添加字段: ```rust /// unclutter 子进程(用于隐藏光标) cursor_child: Option, /// 光标可见性状态 cursor_visible: bool, ``` 2. 在 `capabilities()` 方法中添加 `DeviceCapability::Cursor` 3. 在 `handle_command()` 中实现 `SetCursorVisible` 命令: - `SetCursorVisible(false)` → 启动 unclutter 进程: ```bash pkill -f unclutter # 先清理旧进程 unclutter -idle 0 -root # 立即隐藏光标 ``` - `SetCursorVisible(true)` → 停止 unclutter 进程: ```bash pkill -f unclutter ``` - 参考 ScreenPlugin::set_cursor_hidden 的实现(src/plugins/screen/mod.rs:64-101) 4. 在 `shutdown()` 方法中清理 cursor_child 进程 5. 添加错误处理:unclutter 不可用时记录警告但不阻塞 **输出文件**: - `src/plugins/device/linux_arm64.rs` — 更新后的 Backend 实现 **验收标准**: - [ ] `cargo check --workspace` 零 warning - [ ] `SetCursorVisible(false)` 能成功启动 unclutter 进程 - [ ] `SetCursorVisible(true)` 能成功停止 unclutter 进程 - [ ] 重复调用相同命令不会产生多个 unclutter 进程 - [ ] shutdown 正确清理 cursor_child 资源 - [ ] unclutter 不可用时不阻塞插件启动 **预计工时**: 2 小时 --- ### Task 3: ScreenPlugin 重构 — 改为 DevicePlugin 的 thin wrapper **负责人建议**: 赵雨薇(ScreenPlugin 原作者,熟悉现有实现和消息流) **优先级**: P0(依赖 Task 2) **依赖**: Task 2 必须完成(DevicePlugin 已支持光标控制) **输入文件**: - `src/plugins/screen/mod.rs` — 现有 ScreenPlugin 实现 - `src/plugins/device/mod.rs` — DevicePlugin 实现 - `src/core/message.rs` — 消息定义 **任务描述**: 1. 重构 `ScreenPlugin` 结构体,移除直接硬件操作字段: ```rust pub struct ScreenPlugin { ctx: Option, // 移除 wake_lock_child: Option // 移除 cursor_hidden: bool } ``` 2. 重构 `start_wake_lock()` 方法: ```rust fn start_wake_lock(&self) { if let Some(ctx) = &self.ctx { let envelope = Envelope { from: self.id().to_string(), to: Destination::Plugin("device".to_string()), message: Message::DeviceCommand(DeviceCommand::SetSleepInhibit(true)), }; let _ = ctx.tx.send(envelope); } } ``` 3. 重构 `stop_wake_lock()` 方法(类似,发送 `SetSleepInhibit(false)`) 4. 重构 `set_cursor_hidden()` 方法: ```rust fn set_cursor_hidden(&self, hidden: bool) { if let Some(ctx) = &self.ctx { let envelope = Envelope { from: self.id().to_string(), to: Destination::Plugin("device".to_string()), message: Message::DeviceCommand(DeviceCommand::SetCursorVisible(!hidden)), }; let _ = ctx.tx.send(envelope); } } ``` 5. 保持 `handle_message()` 的消息接口不变: - `Message::ScreenLockRequest(bool)` → 调用 start/stop_wake_lock - `Message::CursorVisibility(bool)` → 调用 set_cursor_hidden 6. 移除所有 `#[cfg(target_os = "linux")]` 条件编译(平台适配由 DevicePlugin 负责) 7. 在文件顶部添加注释说明 ScreenPlugin 现在是 DevicePlugin 的 thin wrapper **输出文件**: - `src/plugins/screen/mod.rs` — 重构后的 ScreenPlugin 实现 **验收标准**: - [ ] `cargo check --workspace` 零 warning - [ ] ScreenPlugin 不再直接调用 systemd-inhibit 或 unclutter - [ ] 所有功能通过 DeviceCommand 消息实现 - [ ] `Message::ScreenLockRequest` 和 `Message::CursorVisibility` 接口保持不变 - [ ] 移除了所有平台特定的条件编译代码 - [ ] 代码行数减少至少 50% **预计工时**: 2 小时 --- ### Task 4: 集成测试 — 验证 ScreenPlugin + DevicePlugin 协作 **负责人建议**: 李思琪(视频引擎工程师,负责阶段一测试,熟悉消息流测试) **优先级**: P1(依赖 Task 3) **依赖**: Task 3 必须完成(ScreenPlugin 重构完成) **输入文件**: - `src/plugins/screen/mod.rs` — 重构后的 ScreenPlugin - `src/plugins/device/` — DevicePlugin 实现 - `src/plugins/device/tests.rs` — 现有测试(参考) **任务描述**: 1. 在 `src/plugins/device/tests.rs` 中添加光标控制测试: ```rust #[test] fn test_set_cursor_visible() { // 测试 SetCursorVisible 命令的序列化/反序列化 } #[test] fn test_cursor_capability() { // 测试 LinuxArm64Backend 报告 Cursor 能力 } ``` 2. 创建 `src/plugins/screen/tests.rs`: ```rust #[test] fn test_screen_lock_request_sends_device_command() { // 测试 ScreenLockRequest 消息转换为 DeviceCommand::SetSleepInhibit } #[test] fn test_cursor_visibility_sends_device_command() { // 测试 CursorVisibility 消息转换为 DeviceCommand::SetCursorVisible } ``` 3. 在 `src/plugins/screen/mod.rs` 中添加 `#[cfg(test)] mod tests;` 4. 编写集成测试文档 `docs/DEVICE_PLUGIN_INTEGRATION_TEST.md`: - 说明 ScreenPlugin 和 DevicePlugin 的消息流 - 提供手动测试步骤(如何验证防息屏和光标隐藏) - 列出测试覆盖的场景 **输出文件**: - `src/plugins/device/tests.rs` — 更新后的测试 - `src/plugins/screen/tests.rs` — 新增测试 - `docs/DEVICE_PLUGIN_INTEGRATION_TEST.md` — 集成测试文档 **验收标准**: - [ ] `cargo check --workspace --all-targets` 零 warning - [ ] `cargo test --workspace` 全部通过 - [ ] 至少新增 4 个测试用例(2 个 device + 2 个 screen) - [ ] 集成测试文档包含清晰的消息流图和手动测试步骤 - [ ] 测试覆盖 ScreenPlugin → DevicePlugin 的消息转换 **预计工时**: 2.5 小时 --- ### Task 5: 文档更新与迁移总结 **负责人建议**: 李思琪(负责阶段一文档,熟悉项目文档结构) **优先级**: P1(依赖 Task 4) **依赖**: Task 4 必须完成(测试通过) **输入文件**: - `docs/DEVICE_PLUGIN_DESIGN.md` — 设计文档 - `.showen/DEVICE_PLUGIN_TASKS.md` — 阶段一任务文档 - `src/plugins/screen/mod.rs` — 重构后的 ScreenPlugin - `src/plugins/device/README.md` — DevicePlugin 文档 **任务描述**: 1. 更新 `docs/DEVICE_PLUGIN_DESIGN.md`: - 在第 6 节"实施计划"中标记阶段二已完成 - 在第 8 节"验收标准"中勾选 ScreenPlugin 迁移项 - 添加"阶段二成果"章节,说明 ScreenPlugin 迁移细节 2. 更新 `src/plugins/device/README.md`: - 在"支持的能力"中添加 Cursor 控制 - 添加"与 ScreenPlugin 的关系"章节,说明迁移历史 3. 更新 `src/plugins/screen/mod.rs` 文件头注释: ```rust //! ScreenPlugin — 屏幕管理(Thin Wrapper) //! //! 本插件现在是 DevicePlugin 的 thin wrapper,通过 DeviceCommand 消息 //! 调用 DevicePlugin 实现防息屏和光标隐藏功能。 //! //! 历史:v0.1.0 直接调用 systemd-inhibit 和 unclutter //! v0.2.0 迁移到 DevicePlugin(2026-03-13) ``` 4. 创建迁移总结文档 `docs/SCREEN_PLUGIN_MIGRATION_SUMMARY.md`: - 迁移前后架构对比图 - 代码行数对比(迁移前 vs 迁移后) - 性能影响分析(消息传递开销) - 未来计划(是否完全移除 ScreenPlugin) **输出文件**: - `docs/DEVICE_PLUGIN_DESIGN.md` — 更新设计文档 - `src/plugins/device/README.md` — 更新 DevicePlugin 文档 - `src/plugins/screen/mod.rs` — 更新文件头注释 - `docs/SCREEN_PLUGIN_MIGRATION_SUMMARY.md` — 迁移总结文档 **验收标准**: - [ ] 所有文档更新完整,反映阶段二成果 - [ ] 迁移总结文档包含清晰的架构对比图 - [ ] ScreenPlugin 文件头注释说明其 thin wrapper 角色 - [ ] 设计文档验收标准已更新 **预计工时**: 1.5 小时 --- ### Task 6: 示例插件完善 — 展示 DeviceCommand 使用(可选) **负责人建议**: 王浩然(网络工程师,可参与示例开发) **优先级**: P2(依赖 Task 5,可延后) **依赖**: Task 5 必须完成(文档更新完成) **输入文件**: - `examples/` — 现有示例代码 - `src/plugins/device/README.md` — DevicePlugin 文档 **任务描述**: 1. 创建 `examples/device_demo.rs`: - 演示如何发送 `DeviceCommand::GetDisplayInfo` - 演示如何发送 `DeviceCommand::SetSleepInhibit` - 演示如何发送 `DeviceCommand::SetCursorVisible` - 演示如何接收 `DeviceResponse` 2. 在 `Cargo.toml` 中添加示例配置: ```toml [[example]] name = "device_demo" path = "examples/device_demo.rs" ``` 3. 添加示例运行说明到 `src/plugins/device/README.md` **输出文件**: - `examples/device_demo.rs` — 示例代码 - `Cargo.toml` — 更新示例配置 - `src/plugins/device/README.md` — 更新运行说明 **验收标准**: - [ ] `cargo check --examples` 零 warning - [ ] `cargo run --example device_demo` 能成功运行 - [ ] 示例代码包含清晰的注释说明每个步骤 - [ ] README 包含示例运行说明 **预计工时**: 2 小时 --- ## 任务依赖关系图 ``` Task 1 (DeviceCommand 扩展 — 光标控制) ↓ Task 2 (LinuxArm64Backend 扩展 — 实现光标控制) ↓ Task 3 (ScreenPlugin 重构 — thin wrapper) ↓ Task 4 (集成测试 — 验证协作) ↓ Task 5 (文档更新与迁移总结) ↓ Task 6 (示例插件完善,可选) ``` ## 团队成员分工建议 | 成员 | 角色 | 负责任务 | 理由 | |----------|----------------|---------------|-----------------------------------------------| | 张明远 | 内核工程师 | Task 1 | 负责阶段一 Message enum 扩展,熟悉类型系统 | | 赵雨薇 | 屏幕工程师 | Task 2, 3 | ScreenPlugin 原作者,熟悉 unclutter 和消息流 | | 李思琪 | 视频引擎工程师 | Task 4, 5 | 负责阶段一测试和文档,熟悉测试框架 | | 王浩然 | 网络工程师 | Task 6(可选)| 可参与示例开发,学习 DevicePlugin 使用 | **核心团队**: 张明远、赵雨薇、李思琪(3 人) **执行模式**: 串行交付(Task 1 → Task 2 → Task 3 → Task 4 → Task 5) ## 关键风险与应对 ### 风险 1: unclutter 在某些 Linux 发行版不可用 **影响**: 中 **应对**: Task 2 中添加错误处理,unclutter 失败时记录警告但不阻塞插件启动,光标控制功能降级为 no-op ### 风险 2: ScreenPlugin 重构后消息传递延迟 **影响**: 低 **应对**: Task 4 中添加性能测试,测量消息传递开销(预计 < 1ms),如果延迟明显则考虑优化 ### 风险 3: 现有依赖 ScreenPlugin 的代码可能受影响 **影响**: 低 **应对**: Task 3 保持 ScreenPlugin 的消息接口不变(ScreenLockRequest/CursorVisibility),确保向后兼容 ### 风险 4: DevicePlugin 未启动时 ScreenPlugin 功能失效 **影响**: 中 **应对**: Task 3 中添加错误处理,DevicePlugin 不可用时记录警告,Task 4 中添加测试验证降级行为 ## 时间估算 | 任务 | 预计工时 | 依赖关系 | 负责人 | |--------|----------|----------|--------| | Task 1 | 0.5h | 无 | 张明远 | | Task 2 | 2h | Task 1 | 赵雨薇 | | Task 3 | 2h | Task 2 | 赵雨薇 | | Task 4 | 2.5h | Task 3 | 李思琪 | | Task 5 | 1.5h | Task 4 | 李思琪 | | Task 6 | 2h | Task 5 | 王浩然(可选)| **总计**: 8.5 小时(必需任务),10.5 小时(含可选任务) **预计完成时间**: 1-1.5 个工作日(假设单人串行) **优化方案**: - Task 1 完成后,赵雨薇可以立即开始 Task 2(无等待) - Task 4 和 Task 5 可以部分并行(李思琪先写测试,再写文档) - Task 6 可以与 Task 5 并行(王浩然独立开发示例) ## 验收总清单 阶段二完成的标志: - [ ] `cargo check --workspace --all-targets` 零 warning - [ ] `cargo test --workspace` 全部通过(包括新增的 4+ 个测试) - [ ] DevicePlugin 支持 Cursor 控制能力 - [ ] ScreenPlugin 重构为 thin wrapper,代码行数减少 50%+ - [ ] ScreenPlugin 和 DevicePlugin 协作正常,消息流测试通过 - [ ] 文档完整更新(设计文档 + README + 迁移总结) - [ ] 手动测试验证:防息屏和光标隐藏功能正常工作 - [ ] 性能测试:消息传递延迟 < 1ms ## 与阶段一的对比 | 维度 | 阶段一(基础框架) | 阶段二(ScreenPlugin 迁移) | |----------------|-----------------------------------|-----------------------------------| | 任务数量 | 5 个任务(4 必需 + 1 可选) | 6 个任务(5 必需 + 1 可选) | | 总工时 | 12-14 小时 | 8.5-10.5 小时 | | 核心团队 | 4 人(张明远/王思远/赵雨薇/李思琪)| 3 人(张明远/赵雨薇/李思琪) | | 关键挑战 | 从零搭建架构 | 重构现有插件,保持兼容性 | | 测试新增 | 5+ 个单元测试 | 4+ 个单元测试 + 集成测试 | | 文档新增 | 设计文档 + README | 迁移总结 + 集成测试文档 | ## 后续规划(阶段三预告) 阶段二完成后,可以考虑: 1. **完全移除 ScreenPlugin**(如果 thin wrapper 无存在价值) 2. **扩展 DevicePlugin 能力**: - 触摸/按钮输入事件 - 传感器数据读取 - 音频播放 3. **添加其他平台后端**: - Android Backend - Embedded (bare-metal) Backend 4. **VideoPlugin 迁移**: - 将 framebuffer 写入迁移到 DevicePlugin.WriteFramebuffer ## 汇报要求 每个任务完成后,负责人需要: 1. 运行 `export PATH="/home/showen/.rustup/toolchains/stable-aarch64-unknown-linux-gnu/bin:$PATH" && cargo check --workspace --all-targets` 验证编译 2. 运行 `export PATH="/home/showen/.rustup/toolchains/stable-aarch64-unknown-linux-gnu/bin:$PATH" && cargo test --workspace` 验证测试 3. 更新自己的 soul 文件,记录本次任务经验 4. 在 `.showen/TEAM_CHAT.md` 中汇报任务完成情况 全部任务完成后,PM 刘建国向 CEO 汇报到 `.showen/inbox/ceo.md`。 --- **文档创建时间**: 2026-03-13 **文档创建人**: PM 刘建国 **文档版本**: v1.0 **基于**: DevicePlugin 阶段一成果(73/73 测试通过)