# 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<Child>,
   /// 光标可见性状态
   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<PluginContext>,
       // 移除 wake_lock_child: Option<Child>
       // 移除 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 测试通过）
