Files
ShowenV2/.showen/DEVICE_PLUGIN_PHASE2_TASKS.md

472 lines
18 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 调用 DevicePluginthin 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 迁移到 DevicePlugin2026-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 测试通过)